perm filename NOTES.JRA[LSP,JRA]31 blob sn#318127 filedate 1977-11-09 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00060 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00006 00002	.SEC(Evaluation of LISP Expressions,Evaluation,,P113:)
C00034 00003	.SS(S-expr Translation of LISP Expressions)
C00050 00004	.SS(Symbol Tables,symbol tables,P92:)
C00061 00005	
C00064 00006	.SS(%3λ%*-notation,%3λ%*-notation,P49:)
C00082 00007	.SS(Mechanization of Evaluation,,P6:)
C00099 00008	.SS(Examples of %3eval%*,examples of %3eval%*)
C00105 00009	.FP
C00116 00010	.<<the |   | symbol table >>
C00130 00011	.SS(Variables,variables,P135:)
C00145 00012	.SS(Environments and Bindings,,P77:)
C00154 00013	.<<RED'S FACT>>
C00158 00014	Notice   that we will get the correct binding of %3x%* locally.
C00162 00015	.CENT(Problem)
C00164 00016	.SS(%3label%*,%3label%*,P38:)
C00172 00017	.SS(Functional Arguments and Functional Values,functional argument,P76:)
C00206 00018	.<<pic of funarg execution>>
C00221 00019	.SS(Binding Strategies and Implementations,binding strategy,P134:)
C00240 00020	.SS(Special Forms and Macros,Special Form,P8:)
C00256 00021	.REQUIRE "NOTES.APE" SOURCE_FILE
C00257 00022	.REQUIRE "NOTES.IMB" SOURCE_FILE
C00258 00023	.SS(The %3prog%*-feature,,P37:)
C00280 00024	The ability to evaluate the argument to %3go%1 results in 
C00287 00025	Now that assignment statements have been described, let's re-examine "<=". 
C00290 00026	.REQUIRE "NOTES.EVA" SOURCE_FILE
C00291 00027	.SS(Function Definitions,,P202:)
C00302 00028	.SS(Rapprochement: In Retrospect,,P90:)
C00327 00029	.ss(LISP Machines,,P175:)
C00331 00030
C00353 00031	The  processor of a "LISP machine" is  →%3eval%*↔←.↓Several "LISP machines"
C00364 00032	.SEC(The Static Structure of LISP,Static Structure,,P188:)
C00376 00033	.SS(Representation of S-expressions)
C00393 00034	.SS(Representation of LISP Primitives,,P26:)
C00406 00035	.SS(AMBIT/G,,P275:)
C00411 00036	.SS(A Few Programming Techniques,,P214:)
C00418 00037	.SS(Symbol Tables and Property-lists,,P128:)
C00434 00038	.GROUP
C00441 00039	.SS(Property-list Functions)
C00446 00040	.SS(An %3eval%* for Property-lists,,P237:)
C00459 00041	.SS(Representation of Property-lists)
C00465 00042	.GROUP
C00477 00043	.FP
C00483 00044	.<<pic of NIL>>
C00488 00045	.SS(Input/Output: %3read%* and %3print%*,,P13:)
C00505 00046	.SS(Table Searching: Hashing,hashing,P14:)
C00515 00047	.GROUP
C00533 00048	.SS(A First Look At ¬3cons¬1)
C00545 00049	.SS(Storage Management: Garbage Collection,garbage collection,P146:)
C00554 00050	.SS(A Simple LISP Garbage Collector,,P280:)
C00565 00051	.CENT(Problems)
C00568 00052	.next page
C00574 00053	.SS(Implementations of Binding,,P78:)
C00587 00054	.SS(Stack Implementation of a LISP subset: Deep Bound,,P148:)
C00594 00055	.SS(Stack Implementation of a LISP Subset: Shallow Bound,,P225:)
C00615 00056	.CENT(An example of shallow binding and %3FUNARG%*)
C00620 00057	
C00627 00058	.ss(Strategies for Full LISP Implementation,,P228:)
C00637 00059	.SS(Epilogue,,P260:)
C00643 00060	.END "JRA"
C00644 ENDMK
C⊗;
.SEC(Evaluation of LISP Expressions,Evaluation,,P113:)
.BEGIN "XX1"
.EP
"... I always worked with programming languages because it seemed to me
that until you could understand those, you really couldn't understand 
computers. Understanding them doesn't really mean only being able to use
them.  A lot of people can use them without understanding them. ..."
.END "XX1"
.BEGIN TURN ON "→";
.PT24
→Christopher Strachey⊗↑[Str#74]↑#######
.END
.PT24;PT24;PT2
.BEGIN "JRA" TURN ON "←","#";
.SS(Introduction)
.BEGIN "INTRO"
%1
.FP
In the previous chapters of this text we have  talked 
about some of the schemes for evaluation.  We have done so rather
informally for LISP; we have been more precise about evaluation
of simple arithmetic expressions. {yonss(P2)} discussed that in
some detail.
We shall now look more closely at the informal
process which we have been using in the ⊗→evaluation↔← of LISP expressions.
This is motivated by at least two desires.

We want to run our LISP programs on a machine.
To do so requires the implementation of a
translator  to turn LISP programs into instructions which
can be  carried out by a conventional machine.
We will be interested in the structure of such implementations.
Any  implementation of LISP must be grounded on a precise,
and clear understanding of what LISP-evaluation 
entails. Indeed, a deep understanding 
of evaluation is a prerequisite for implementation of %6any%* 
language.⊗↓The question of evaluation cannot be sidestepped by basing a language
on a compiler. A compiler must produce code which when executed, simulates 
the evaluation process.← 


Our second reason for pursuing evaluation involves the question
of programming language specification.
At a practical level we want a clean, machine independent,⊗↓By
"machine independent" we mean independent of any specific
hardware implementation. A programming language, almost
by definition, is a machine specification. What we
would like is a "sufficiently high level" machine.← "self-evident"
language specification, so that the agony involved
in implementing the design can be minimized.  At a more abstract level,
we should try to understand just what %6is%* specified when we design a 
language. Are we specifying a single machine,  a class of machines, or a
class of mathematical functions? Just what is a  programming language?
The syntactic specification of languages is reasonably well established,
but syntax is only the tip of the iceberg. Our study of LISP
will address itself to the deeper  problems of semantics, or meaning,
of languages.

Before we address the direct question of LISP evaluation, we
should perhaps wonder aloud about the efficacy of studying languages in the
detail which we are proposing.
As computer scientists we should  be curious about the
structure of programming languages because we
 must understand our tools
--#our programming#languages. People who simply wish to
%6use%* computers as  tools need not
care about the structure of languages. Indeed they usually
couldn't care less about the inner workings of the language; they only
want  languages
in which they can state  their problems in a reasonably
natural manner.
They want their programs to run and get results. They are interested in
the output and seldom are interested in the detailed process of
computation.
For a simple analogy,  consider  the field of mathematics.
The practicing mathematician uses his tools --#proofs#-- in a similar
manner to the person interested in computer applications.
He seldom needs to examine questions  like "what is a 
proof?" He does not analyze his tools.
However not so many years ago
such questions %6were%1 raised, and for good reason.
Some common  forms of reasoning  were shown to lead to
contradictions unless care was taken.

Our position is more like that of the  foundations of mathematics;
there the tools of mathematics %6are%* studied and analyzed.
 Mathematics has flourished because of it. Though our expectations
are not quite that presumptuous, we %6do%* expect that
programming language design cannot help but be improved.

Our study of language implementation will proceed from the abstract to
the concrete. Each level will intimately involve the study of data structures.
The next two chapters will be the most abstract, building a precise
high-level description of an evaluation scheme for LISP. In fact,
the discussion is much more general than that of LISP; the text addresses
itself to problem areas in the design of any reasonably sophisticated 
language. In subsequent chapters we probe beneath the surface of this
high-level description and discuss common ways of implementing
the necessary data structures and control structures.
In the process we will not only understand LISP but will develop
a firm understanding of virtually any other language.

But how can we begin to understand LISP evaluation?  
In {yonss(P2)} we made a beginning, giving an algorithm for
a subset of the computations expressible in LISP.
This subset covered evaluation of some simple arithmetic expressions.
From our earliest grade school days we have had to evaluate simple
arithmetic expressions. Later, in algebra we managed to cope with
expressions involving function application. Most of us survived the
experience. We should now try to understand the processes we used in these
simple arithmetic cases, doing our examination at the most mechanical
level.
The basic intent of the algorithm is fixed: evaluate the expression; but within
that general constraint we often have several distinct alternatives.
Those places at which we have  choices   should be remembered. 
We will make reasonable choices so that
the process  becomes deterministic and then proceed. Later, we should
reflect on what effect our choices had on the resulting scheme.
For example, recall the discussion of the representation of symbol tables on 
{yon(P186)}. We had several options, but picked one which seemed to 
satisfy our intuitions and was reasonably efficient. 
But we should subject that decision to close scrutiny: does it
really  fulfill our expectations? In absence of
absolute standards, these questions are usually answered by examining the
behavior of the algorithm.

The first thing to note in reflecting on simple arithmetic
examples is that %6nothing%* is really said about the process
of evaluation.  
When asked to evaluate
%3(2*3)#+#(5*6)%* we never specified which summand was to be evaluated first.
Indeed it didn't matter here. %36#+#(5*6)%*  or %3(2*3)#+#30%* both
yield  %336%*.
Does it %6ever%*  matter? Sums and products are examples of arithmetic operations; 
can we always leave
the order of evaluation unspecified for arithmetic operations? 
What about evaluation of arbitrary functional expressions?
If the order doesn't matter, then the specification of the evaluation
process becomes much simpler. If it %6does%* matter then we must
know why and where.


.P98:
We have seen that the order of  evaluation %6can%* make a difference in LISP.
On {yon(P106)} we saw that %2CBV%1, LISP's computational
interpretation of function application, requires some care.
On {yon(P17)} we saw that order of 
evaluation in conditional expressions can make a difference. 
Since we are using %2CBV%1 we must  make %6some%* decision regarding
the order of evaluation of the arguments to a function call,
say %3f[t%41%*;t%42%*;#...;t%4n%1].  We will assume that we will evaluate the arguments
from left to right.  This second decision about the order of evaluation can also
effect the computation.

Consider the example due to J. Morris:

.P84:
.BEGIN CENTERIT;
.BOXA
←%3f[x;y] <= [x = 0 → 0; %et%* → f[x-1;f[y-2;x]]]%1  
.BOXB
.END
.FP
Evaluation of %3f[2;1]%*
will terminate if we always evaluate the outermost occurrence of %3f%*.
Thus:
.BOXA
←%3f[2;1] = f[1;f[-1;2]] = f[0;f[f[-1;2]-2;1]] = 0%*
.BOXB
.FP
However if we evaluate the innermost occurrences⊗↓The notions of "innermost"
and "outermost" evaluation need to be slightly embellished for multiple-argument
 applications. If the chosen application has several arguments, then
we must specify an order for their evaluation. 
Thus terms like "leftmost-outermost"
and "rightmost-innermost" occur. For example, the  LISP scheme is an instance of
"leftmost-innermost" evaluation.←
first, the
computation will not terminate:
.BOXA
←%3f[2;1] = f[1;f[-1;2]] = f[1;f[-2;f[0;-1]]] = f[1;f[-2;0]] = ... %*
.BOXB
The choice of evaluation schemes has far reaching consequences.
The evaluation scheme, %2CBV%1, which we chose
is called %2⊗→call-by-value↔←%*.  It is called 
applicative order evaluation or %2inside-out%*  style of evaluation,
meaning that we evaluate the subexpressions before evaluating the main expression.
Alternative proposals exist;
  ⊗→call-by-name↔←  evaluation, also called normal order evaluation,  is another
common scheme. We introduced this outside-in scheme on {yon(P126)} as %2CBN%*.
From an implementation
perspective,  call-by-value
is favored; these issues will be discussed soon.
However those advantages must be weighed against the
knowledge that call-by-value
may lead to non-terminating computations when call-by-name would terminate.⊗↓There
are also examples where call-by-value will terminate but call-by-name will not.
See {yon(P278)}.← 

Informally, call-by-value says:
evaluate the arguments to a function before you  apply the
function definition to the arguments.
Let's look at a simple arithmetic example.
Let %3f[x;y]%*  be %3x%82%*#+#y%1 and consider %3f[3+4;2*2]%*.  Then
call-by-value says evaluate the arguments, getting %37%* and %34%*; 
associate those values
with the formal parameters of %3f%* (i.e. %37%* with %3x%* and 
%34%* with %3y%*) and then evaluate the body of
%3f%* resulting in #%37%82%*#+#4#=#53%1. This is the scheme we
captured in {yonss(P2)}.

Call-by-name says pass the %6unevaluated%* actual 
parameters to the function, giving  %3(3+4)%82%*#+#2*2%1.
This expression will simplify to %353%*. 
In general,
evaluation can be described as "substitution followed by simplification";
the different evaluation schemes  involve different choices about the order 
in which those operations are performed.
We will say more about call-by-name and other styles of
evaluation in {yonss(P85)} and {yonss(P268)}.
Most of this chapter will be restricted to call-by-value.

.GROUP;
If you look at the structure of %3value%9''%1 and %3apply%9'%1 beginning
on {yon(P125)} you will see that they encode a   call-by-value strategy
 and have  the followng  interpretation:
.PT24
.NL
%21.%*##If the expression is a constant then the value
of the expression is that constant.  (The value of %33%* is %33%*).⊗↓We 
are ignoring the distinction between the %6numeral%* %33%* 
and the %6number%3 3.%1←
.APART
.NL
%22.%*##If the expression is a variable then see what the current value associated
with that variable is. Within the evaluation of, say,
%3f[3;4]%* where %3f[x;y]#<=#x%82%*#+#y %1the current value of the variable
%3x%* is %33%*.  
.NL
%23.%*##The only other kind of arithmetic  expression that we can have is a function
name followed by arguments, for example  %3f[3;4]%*.  
In this case we first evaluate the arguments ⊗↓Here we are using the evaluation
process recursively.←
and then apply the definition of the function to those
evaluated arguments.  When  we apply the function definition
to the evaluated arguments   
we associate  the formal parameters 
of the definition with the values of the actual parameters.
This process of associating parameters is called %2binding%1 and
simulates some form of substitution.
We then evaluate the body of the function using this new environment.  
Notice that we do %6not%* explicitly substitute the values for the variables
which appear in an expression. We %6simulate%1 substitutions by table lookup.
.boxb

.P80:
We want to apply this treatment of evaluation to LISP expressions.
If the LISP expression is a constant, then the value of the
expression is that constant.
The constants of LISP  are the S-exprs. 
Thus
the value of %3(A#.#B)%* is %3(A#.#B)%*, just like the value of %33%* is %33%*.
Variables and functional applications appear in LISP and are handled similarly to
 %22%1 and %23%1 above.
The additional artifact of LISP 
 is the conditional expression. But  its evaluation can also
be precisely specified. We did so on {yon(P40)}.
.GROUP;
In more specific detail, here is some of the structure of the
LISP evaluation mechanism:
.PT24
.NL
%21.%*##If the expression to be evaluated is a constant then the value
is that constant.
.APART;
.NL
%22.%*##If the expression is a variable find its value in the current environment.
.NL
%23.%*##If the expression is a conditional expression then it is of the form
%3[%2p%41%3#→#%2e%41%3;#%2p%42%3#→#%2e%42%3;#...#;%2p%4n%3#→#%2e%4n%3]%1.  
Evaluate it
using the semantics defined on {yon(P40)}.
.GROUP;
.NL
%24.%*##If the expression is of the form: %3f%1[%3t%41%3;t%42%3;#...#;%3t%4n%3]%1
 then:
.BEGIN INDENT 10,12;GROUP;TURN ON "\";TABS 8,12;
.fp
\%2a.%1\Evaluate the arguments %3t%41%3,#t%42%3,#...#,#%3t%4n%1   
from left to right.
.fp;pt2
\%2b.%1\Find the definition of the function, %3f%1.
.fp;pt2
\%2c.%1\Associate the evaluated arguments with the formal parameters 
in the function definition.
.fp;pt2
\%2d.%1\Evaluate the body of the function, while remembering the values
of the variables.
.END
.APART
.boxb
We saw in ({yonss(P2)}) that a simple kind of arithmetic 
 evaluation can be transcribed into a recursive LISP algorithm.
That algorithm operates on a representation of the expression and
produces the value. Most of our work in that example was done
without giving explicit details of the representation.
We had previously given a detailed representation
in {yonss(P41)}.

We have demonstrated an informal, but reasonably precise,  evaluation scheme 
for LISP;
our discussion  is ready for  more formal development.
It should be clear that we could write a LISP
function representing the evaluation process provided that we can
find a representation for LISP expressions as S-expressions. 
This mapping, %eR%*, of LISP expressions to S-exprs is our first order of business. We 
will accomplish this mapping by using an extension of the scheme introduced in
{yonss(p41)}.


The rationale for mapping LISP expressions onto S-exprs  and writing a LISP 
function to act as an evaluator may seem overly opaque, but
the mapping is no more obscure than that in the polynomial evaluation or 
differentiation examples.
It is just another instance of the diagram of {yon(P46)},
only now we are applying the process to LISP itself.  
Once the representation is given we will produce  a LISP 
algorithm which describes the
evaluation process used in LISP.
The effect is to force
us to make precise exactly what is meant by LISP evaluation. This
precision will have many important ramifications. The first dividend
is an abstract, compact, and high level description of a LISP
machine.

.next page
In terms of the diagrams on {yon(P46)} we have:

.BEGIN GROUP;TABIT1(32);
.BOXA
LISP evaluation   => LISP evaluation algorithm
 Call-by-value          %3eval%1\|
\| LISP evaluation
\|=====> %eR%f(%3A%f)%1 interpret this output 
\|                            as answer %3A%1 
\|
expression  => Representation
 %3car[(A . B)]       %eR%f(%3car[(A . B)]%f)%3
.BOXB
.END
.GROUP;
.FP
The diagram is %6almost%1 circular. We evaluate an evaluation algorithm
named %3eval%1. We break the circle by supplying a lower-level implementation of 
the original evaluator. That will be the subject of {yonsec(P188)} and
{yonsec(P107)}. With that, our diagram reduces to:


.BEGIN tabit3(12,34,40);
.BOXA
LISP expression  =>   =>\Representation     
  %3car[(A . B)]\  %eR%f(%3car[(A . B)]%f)%1
\\\↓↓
\\LISP evaluation 
\\\%3eval%1
\\\↓↓
\\Representation of answer 
\\     %eR%f(%3A%f)%1 
.BOXB
.END
.APART

.GROUP;
.FP
This picture  reflects two points: we should pick a representation
such that the reinterpretation of the answer is easy. We should also
pick a representation such that the representation of the expression
is easy. If those two conditions are satisfied, then we might as well
write our programs in the representation and do the input and output transformations
ourselves. With this in mind we can simplify further to:

.BEGIN CENTER;
.P269:
.BOXA
%eR%f(%3car[(A . B)]%f)%1### ==a LISP evaluation algorithm=>###%eR%f(%3A%f)%1 
.BOXB
.END
.FP
This last diagram reflects the typical LISP programming language. We program using
the data structure representation.
.APART;

We've already seen the evaluation of  representations of
LISP expressions.
The %2great progenitor of all functions%* is an evaluation algorithm for 
the LISP primitive functions and predicates, %3car, cdr, cons, atom%* and %3eq%*
when restricted to functional composition and constant arguments.
The representation used there was a list representation, and exemplifies a 
notation which we will develop further.

In the next section we will give a specific mapping of LISP expressions
onto lists and S-exprs.
 But remember that we should attempt
to keep the knowledge of the representation out of the structure
of the algorithm.
Let's stop for  a 
description of the  representation and
some examples of translating LISP functions into that representation.


.END "INTRO"
.SS(S-expr Translation of LISP Expressions)
.BEGIN "SEXPR"
.FP
We will go through the list of LISP constructs, describing the
effect of the representational map, %eR%*, and give a few examples
applying %eR%*.
The first class of LISP objects we represent are the numerical constants.
%1We will represent numerals just as numerals, e.g.:
.BOXA
.BEGIN "XX4" CENTERIT;
.EQ1(25)
\%eR%f(%1 <numeral> %f)%3 = %1<numeral>
\%eR%f(%3 2 %f)%3 = 2
.END
.END "XX4"
.BOXB
Other simple components of LISP syntax include the identifiers used
as variable names and function names; and of course the LISP atoms 
and S-exprs themselves.
We want to represent identifiers and S-exprs as S-expressions. The first request
is understandable, but perhaps the second request seems vacuous: LISP S-exprs
%6are%1 S-exprs. Both requests are justifiable as we shall now see.
.group
In the evaluator, identifiers are used as variables; therefore we might
represent a variable %7i%1 as:
.boxa
.begin center
%eR%f( %7i%f )%1  = %3(VAR %7i%3)%1
.end
.boxb
.apart
.FP 
For example %3x%1 could be represented as %3(VAR#X)%1.

Every LISP expression must have a representation; and the mapping
function must be such that we can recover the original object from
its representation. From %3(VAR#X)%1 we can  tell that it is a representation
of the variable %3x%1.
Now consider the representation of the non-numerical LISP constant:
atoms and S-exprs. Since %3(VAR#X)%1 is a LISP constant, it must
have a representation under our mapping. We cannot represent the
expression as itself since that would violate our inverse mapping
property. Following our discussion of variable representation, we 
could represent  a constant %7a%1 as:
.boxa
.begin center
%eR%f( %7a%f )%1  = %3(CONST %7a%3)%1
.end
.boxb
.GROUP
.fp
This mapping will solve the problems; we can 
.boxa
.fp
map the list #######%3(VAR#X)%1### to### %3(CONST (VAR X))%1
.BOXB
.APART
.group
.boxa
.begin tabit1(25);
\%eR%f( %3x%f )%1  = %3(VAR %3X%3)%1
.pt2
\%eR%f( %3X%f )%1  = %3(CONST %3X%3)%1  ⊗↓To be consistent, we should
represent numerals in this format too.←
.end
.boxb
.apart
When this maping is extended to represent %6all%1 LISP expressions
the resulting expressions become very complex. Since we wish to
use the mapped expressions as the programming language, human engineering
considerations beg for a simplification. Therefore we use the following 
map:
.group
.boxa
.begin tabit1(25);
\%eR%f( %3x%f )%1  = %3X%1
.pt2
\%eR%f( %3X%f )%1  = %3(QUOTE %3X%3)%1
.end
.boxb


%1That is, we will translate identifiers to their upper-case counterpart. 
.BOXA
.BEGIN "XX5" CENTERIT
.EQ1(23);
Thus:\%eR%f( %1<identifier> %f)%3 = %1<literal atom>
.boxa
Examples:\%eR%f( %3x %f)%3 = %3X
\%eR%f( %3y2 %f)%3 = %3Y2
\%eR%f( %3car %f)%3 = %3CAR
.END
.END "XX5"
.BOXB
.APART

.GROUP
.fp
The mapping for LISP constants is:
.SELECT 1;
.BOXA
.BEGIN CENTERIT
←%eR%f( %1<sexpr> %f)%3 = %3(QUOTE %1<sexpr>%3)%1
.END
.BOXB
.FP
.BOXA
.BEGIN "XX6" CENTERIT
.FP
.EQ1(23)
%1For example:%3\%eR%f( %3X %f)%3 = %3(QUOTE X)%1
\%eR%f( %3(A . B) %f)%3 = %3(QUOTE (A . B))%1
\%eR%f( %3QUOTE %f)%3 = %3(QUOTE QUOTE)%1
.END
.END "XX6"
.BOXB
.APART
.GROUP
%1
.BEGIN FILL;
We must extend the mapping to the other constitutients of the language.
We must  map applicative expressions of the form %3f[e%41%*#;#...#;e%4n%*]%1
onto  S-exprs.
Following
the style of our initial mapping, we might map %3f[x]%1 onto
something like %3(APP#(VAR#F)#(VAR#X))%1 or %3(APP#(FUN#F)#(VAR#X))%1,
 signifying that the 
list represents an applicative expression. However this leads to
cumbersome expressions.
We have  seen one other mapping for functions in prefix form
in {yonss(P41)}.
We will use that mapping, called Cambridge Polish,⊗↓The name, Cambridge Polish,
is derived from two sources: Cambridge, since M.I.T. is in Cambridge Massachusetts,
and McCarthy was at M.I.T. while developing his ideas; Polish, since the representation
is a dialect of a  notation developed by a school of Polish logicians.←  here. That is:
.END
.BOXA
.BEGIN TURN ON "←";
←%eR%f( %3f[e%41%*;e%42%*; ...;e%4n%*] %f)%3 =
( %eR%f( %3f %f)%3 %eR%f(%3 e%41%* %f)%3 %eR%f(%3 e%42%* %f)%3 ... %eR%f(%3 e%4n%* %f)%3 )%1
.END
.BOXB
.APART
.GROUP
.BEGIN "XX2" CENTERIT;
.FP
%1Examples:%3←%eR%f( %3car[x] %f)%3 = (%eR%f( %3car %f)%3 %eR%f( %3x %f)%3 ) = (CAR X)
.EQ1(7);
\%eR%f( %3car[X] %f)%3 = (%eR%f( %3car %f)%3 %eR%f( %3X %f)%3 ) = (CAR (QUOTE X))
\%eR%f( %3cons[cdr[(A . B)];x]  %f)%3 = (CONS (CDR (QUOTE (A . B))) X)  
.END
.END "XX2"
.BOXB
.APART
.GROUP

%1The %eR%*-mapping must also handle conditional expressions. A conditional is
represented as a list whose first element is ⊗→%3COND%*↔← and whose next %3n%*
elements are representations of the %3p%4i%*-e%4i%1 pairs. The %eR%*-map
of such pairs is a list of the %eR%*-maps of the two elements:

.BOXA
.BEGIN TURN ON "←";TABIT1(45);
←%eR%f( %3[p%41%* → e%41%*; ... ;p%4n%* → e%4n%*] %f)%3 = (COND\(%eR%f(%3 p%41 %f)%3  
\%eR%f(%3 e%41%f)%3 ) 
\   . . .
\(%eR%f(%3 p%4n%3 %f)%3 %eR%f(%3 e%4n %f)%3))
.BOXB
.END
.BEGIN TURN ON "←";TABIT1(44);
%1An example:%3
.PT2
←%eR%f( %3[atom[x] →1; q[y] → X] %f)%3 = (COND\((ATOM X) 1) 
\((Q Y) (QUOTE X)))
.END
.BOXB
%1
.APART
.P44:
.FP
Notice that %3(COND#...#)%* and %3(QUOTE#...#)%* %6look%* like translations
of function
applications of the form %3cond[#...#] %* and %3quote[#...#]%*. 
However since we expect application to be performed using call-by-value,
we must handle these constructs in a special manner.
Indeed,  %3quote[%9α%3]%1 stands for %eR%f(%9α%f)%1. Similarly
 the "arguments" to %3cond%1 are not to be interpreted as  in
function applications; for example, %3COND#((ATOM#X)#1)#...)%1 does not
represent %3cond[#atom[x][1];#...#]%1.

Finally, the translations of the truth  values  %et%1 and %ef%1 will be
%3T%* and %3NIL%*, respectively.
.BOXA
.BEGIN "XX7" CENTERIT;
.EQ1(37);
\%eR%f( %et%* )%3 = T
\%eR%f( %ef%* )%3 = NIL
.END
.END "XX7"
.BOXB
.FP
You might have noticed that these last two applications of the 
chosen %eR%*-mapping
have the potential to cause trouble. They will spoil the 1-1 property of %eR%*:
.BOXA
.BEGIN "XX8" CENTERIT;
.EQ1(37);
\%eR%f( %3t%* )%3 = T
\%eR%f( %3nil%* )%3 = NIL
.END
.END "XX8"
.BOXB
.FP
The usual way to  escape from this difficulty  is to outlaw %3t%* and
%3nil%* as LISP variables.⊗↓In LISP#1.5 %3T%1 and %3F%1 were used as the representations of 
%et%1 and %ef%1; the atoms %3T%1 and %3F%1 were (permanently) bound to values
%3*T*%1 and %3NIL%1. Note too, that our initial mapping could 
solve the problem by mapping %3t%1 to %3(VAR#T)%1 and mapping %et%1 
to %3(BOOL#T)%1.←  

Perhaps our concern for the %eR%*-mapping's properties appears heavy-handed
where a simple solution seems
apparent: %et%* is %et%* and %3t%* is %3t%*; when we
want the truth value we write %et%* and when we want the variable we
write %3t%*. The answer  is that when we write programs for a
machine version of LISP, we will be writing
the %eR%*-image, rather than the more traditional syntax. Thus to
ask a LISP machine to evaluate %3car[(A#.#B)]%* we present it
with %3(CAR#(QUOTE#(A#.#B)))%*.   What this means is that we are presenting
our programs to the machine as data structures of the language.⊗↓Compare this
with the technique of Godel numbering in formal logic ⊗↑[Men#64]↑.← 
It would be like expressing programs in Fortran or Algol as
arrays of integers; that is, the data structures of %6those%* languages.
We will explore the implications of this
approach to programming in later sections.

In essence, then, there are %6two%1 LISP's: there is the algorithmic language
and there is the programming language. The programming language
is a data structure representation of the algorithmic language.
The algorithmic language is called the %2⊗→meta-language↔←%1 or 
%2⊗→M-expr LISP↔←%1,
and for historical purposes, the programming language is called %2⊗→S-expr LISP↔←%1.


Review the %3tgm%*'s ({yonss(P39)})  now 
that you understand that they are evaluators for simple subsets of LISP expressions;
discover what LISP expressions were encoded in arguments  to the %3tgm%1's
and verify the answers you obtained earlier.
Note that the only atoms which the great
mothers recognize are  %3T%* and %3NIL%*. Any other atoms
elicit an error message.
What do  other atoms represent? 
Numerals are atoms and are the %eR%*-maps of
numerals. We  could extend %3tgmoaf%* to handle this case.
Atoms are also translations of 
variables and function names.
So one task is to include a mechanism in our  LISP
evaluator to handle evaluation of variables and function names. 
We have already seen
the necessary mechanism in {yonss(P2)} where we studied tables as  abstract
data stuctures. The other piece of LISP which did not appear in the evaluator
for polynomials was conditional expressions.
Conditional expressions %6were%1 handled in %3tgmoafr%1. The "progenitors"
did %6not%1 handle variable references, however. In preparation
for that  work we reexamine the issues of symbol tables.
.END "SEXPR"
.SS(Symbol Tables,symbol tables,P92:)
.BEGIN "SYMTAB"
%1
.FP
One distinguishing feature of computer science is
the ubiquity  of devices to store and recover information.
A notation  which addresses  itself to computer science
must treat this aspect.
In hardware oriented languages and some high level programming languages
we find the notion of "cell" or "location" and find operations to explicitly
deposit and examine information in those cells.
Our LISP subset has no such explict features; it relies on the implementation
of binding and variable evaluation to perform similar notions.
As part of our examination of evaluation we wish to expose these details
to close scrutiny and understand how binding and variable evaluation
can be mechanized.  The most  common notion used to implement these operations
is the  symbol table.⊗↓Recall, we are %6simulating%1 substitution;
see ⊗↑[Ber#75]↑ for an alternative.←
This is the device we used informally in {yonss(p2)};
we will review some of that discussion here.

In its abstract form, a symbol table is  a set of ordered pairs
of objects; one of the
elements of each pair is a name;  the other is a value associated with that name.
This means that symbol tables can be characterized as relations or perhaps
even as functions.
This latter characterization is indeed viable. On {yon(P186)} we showed that 
a table could be constructed and maintained in a manner preserving functionality.
As an abstract operation, finding an element in a symbol table is also
quite simple: given a set of ordered pairs and a name,
find a pair whose first element is the same as the given name.
This operation can be described as function application where the function
being applied is the table and the argument is the name component.
That is: ###%3locate[x;tbl]#=#tbl(x)%1.

The maintenance of symbol tables as  sets was a bit too abstract;
the level of abstraction we  implemented viewed a
symbol table as a %6sequence%* of pairs, each pair representing a variable
and its corresponding value.  
The  table manipulating
algorithms, given in {yonss(P2)},  depended 
heavily  on the implied sequencing of call-by-value and recursion.
Since this was consistent with the explicit sequencing used in adding
elements to the table, we achieved the desired effect. We found the
expected bindings, even though there may have been other candidates in the
tables. In the remaining sections of this chapter we will utilize more
features of this interplay between representation of data and calling style
of algorithm. Symbol tables are just one manifestation of this
phenomenon.

Symbol tables are also known as ⊗→association lists↔←
or %2⊗→a-lists↔←%*;
thus %3assoc%* is the traditional name of a LISP function to  
search  a symbol table. 
More recently symbol tables have been called %2environments%1; thus
we frequently will use the identifer %3env%1 as a variable which
is an environment.
The binary function 
%3assoc%* expects  a name and a symbol table as arguments.
It will examine the table from left to right, looking for the first
pair whose name-component matches the given name.
If  a pair is found,
then that pair is returned;  if no such pair is found, the
result is undefined.
We will need to designate a selector, %3name%*, to locate
the name-component of a pair, and another selector, %3value%*, to
retrieve the value-component.

.BEGIN TABIT2(10,28);GROUP;
.SELECT 3;
.BOXA
\assoc[x;env] <= \[eq[name[first[env]];x] → first[env];
\\ %et%* → assoc[x;rest[env]]]
.BOXB
.END
If the table is very long and the desired pair is close to the 
end of the table, then we will be in for a very long search. The search
scheme encoded in %3assoc%1 is called %2⊗→linear search↔←%1, and is
 unnecessarily inefficient for tables of
substantial length. However the phenomemona we wish to study now are
not directly related to efficiency of searching methods.⊗↓At least indirectly
the discussion %6is%1 related to search efficiency. LISP implements
a dynamic binding or "latest active" binding strategy. A case can be
made for static binding on the basis of shorter symbol table searches.←
We will come back to symbol tables in {yonss(P128)} to study 
the problems of efficient storage and retrieval of information. 
It will suffice now simply to think of a symbol table as represented
in LISP by a list of dotted pairs: a  name  dotted with value.
In this representation, then, %3name[x] <= car[x]%*, and %3value[x]#<=#cdr[x]%*.
For completeness, we should also specify a constructor. Though we
won't need the function for a while, we will name it ⊗→%3mkent%*↔←; it
will take an identifier and a value and return a new 
symbol table entry. Its representation here is
%3mkent[x;y]#<=#cons[x;y]%*.


.GROUP
.P110:
To illustrate the representation and algorithms, assume we wish to
represent three variables
 %3x, y, %*and %3z%*  which were to have
 values %32, 3, %*and %34%*. That fact could
be encoded as:
.boxa
.ONCE CENTER
%3((X . 2) (Y . 3) (Z . 4))%1
.APART
.GROUP
.BOXB
.BEGIN "XX8" CENTERIT;GROUP;
.FP
Then the retrieval of %3y%1 and %3u%1 could be encoded as:
.EQ1(19)
\%3assoc[Y; ((X . 2) (Y . 3) (Z . 4))] = (Y . 3)
\%3assoc[U; ((X . 2) (Y . 3) (Z . 4))] %1 = %9B%1  
.END
.END "XX8"
.BOXB
.APART
%1
.FP
The retrieval of %9B%1 for %3u%1 could be implemented as an error message or,
better yet, could interact with the user to isolate the misconception,
correct it, and continue.

We must also represent bindings of variables to non-numeric S-exprs.  For example,
we must represent information like: 
"the current value of %3x%* is %3A%*".
We will place the dotted-pair %3(X . A)%* in the table. Now this
representation is certainly open to question: why not add
%3(X#.#(QUOTE#A))%*?  The latter notation is more consistent
with our conception of representation espoused on {yon(P46)}.
That is, we map LISP expressions to S-expressions; perform the
calculations on this representation, and finally %6reinterpret%*
the result of this calculation as a LISP expression. The representation
we have chosen for symbol tables obviates the last reinterpretation
step; recall the diagram on {yon(P269)}. 
Now it will turn out that for our initial subsets of LISP
this reinterpretation step simply would involve "stripping" the %3QUOTE%*s.
The only "values" which a LISP computation can return are constants; 
however more general evaluation schemes are conceivable;  partial
evaluation may be useful, 
simplifying %3x+y+2%1 to %3x+6%1 when %3y%1 has value %34%1.
Perhaps the LISP representation of 
table entries is a poor one; we will see. 
In studying any existing language, or contemplating the design of
any new one, we must question each detail of representation. Decisions
made too early can  have serious consequences.


Before continuing  we should take stock of our current
position. In this section
we have  recreated the table-lookup mechanism we used
in {yonss(P2)}, but  now we are paying a bit more attention
to representation. 
We can locate things in a table and we have seen how calling 
functions can add values to a table. We have said nothing
about adding function definitions to the tables.
Abstractly we know how to extract the definition from the table and
apply it. We must give an explicit representation of the storage of a
function. This turns out to be a reasonably non-trivial problem.
We have seen that it is possible to mechanize at least one 
scheme for evaluation of functions -- call-by-value, evaluating arguments from
left to right.
We have seen that it is possible to translate LISP expressions
into S-exprs in such a way that we can write a LISP function
which will act as an evaluator for such translations.  In the process
we have had to mechanize the intuitive devices we   might mentally
use to recall the definition of functions and to recall the current
values of variables.  It became clear that the  mechanism
 of symbol tables could be used.  To associate a variable with
a value was easy.  To associate a function name with its definition
required some care.  That is, part of the definition of a function 
involves the proper association of formal parameters with the
body of the definition. The next section introduces a notation 
for describing function definitions.

.END "SYMTAB"
.SS(%3λ%*-notation,%3λ%*-notation,P49:)
.BEGIN "LAMBDA"
.BEGIN TURN ON "←";
.FP
Recall our discussion of the problems of representation of function
definitions. This discussion began on {yon(P124)} and our conclusion was
that to represent a definition like %3f[x;y]#<=#%9x%1
we  needed a symbol table entry with name %3f%* and a value part which
contained the body of the definition, %9x%1, and the
list of formal parameters, %3[x;y]%*.
This view of the content of a definition will have to be revised,
but its implementation contains sufficient complexity to support a lively and
fruitful discussion.
LISP uses  a unique notation, called the λ-%2notation%1 to 
lend precision to our informal
discussion of function representation. 

The λ-notation is derived from  the %9λ%1-calculus, a formalism invented 
by the logician Alonzo Church (⊗↑[Chu#41]↑) to 
model functions which are describable by algorithms.
The %9λ%1-calculus is useful for discussing the concepts of function and
function application. Since many algorithms compute functions and since
function application is simulated by procedure calls, the calculus is well
suited for a
purified discussion of procedures in programming 
languages. We shall outline the
%9λ%1-calculus in {yonss(P85)}.
The λ-notation  was introduced into programming languages by John McCarthy in 
the description of LISP (⊗↑[McC#60]↑).
There are several
important distinctions between Church's %9λ%1-calculus and the λ-notation of
McCarthy; we will point out the differences in {yonss(P85)}.

We begin the discussion by exemplifying the need for more precise terminology.
We have been informally writing %3f[x;y]#<=#x*y#+#y%* as 
a definition of the function %3f%*. This notation is 
supposed to convey the following
intent: %3f%1 is the name of a function or rule; whenever %3f%1 is supplied
with two numeric arguments it is supposed to multiply those arguments
and add the result to the second. The resulting sum is the desired answer.
Since informality is susceptible to ambiguity, we should
analyze the "<="-notation more closely. Though we say %3f%1 is being
defined, it is not %3f%1, but %3f[x;y]%1 which appears to the left of the 
"<="-symbol.
First,  %3f[x;y]%* does %6not%* denote a function, %3f%* denotes a function.
To see what  %3f[x;y]%* means consider the following example.
When we are asked to evaluate %3car[(A#.#B)]%* we say the value is %3A%*.
##%3car[(A#.#B)]%* is an expression to be evaluated; 
we have called such expressions  LISP %2⊗→form↔←s%1.
If %3car[(A#.#B)]%*  is a form then so is %3car[x]%*; 
only now the form references a variable instead of a constant;
therefore the value of the
form depends on the current value assigned to the variable %3x%*.
So the %2⊗→function↔←%* is %3car%*; the %2form%* is %3car[x]%*.
Therefore,
the function is %3f%*; %3f[x;y]%* is a form, and so is %3x*y#+#y%*.
The informal notation has a form on both sides of the "<=". 
We would like a notation which clearly shows what is being defined and
what is given.

Further, our notation has really been specifying more than just the name.
The notation specifies  the formal parameters (%3x%* and %3y%*) and
the order in which we are to associate actual parameters in a call 
with the formal parameters of the definition (%3x%* with the first, %3y%* with the second).
More subtly, the notation tells %6which%* variables in the function body
are to be supplied values when the
function is called. For example define %3g[x]#<=#x*y#+#y%*; then the
expression %3g[2]%* specifies that %3x%1 is to receive a value %32%1, but
leaves unspecified what the value of %3y%1 should be.⊗↓Note also,
that the "values" for +  and * are also unspecified.← 

We also wish to have a notation 
so that function definitions can be inserted into the symbol
table as "values" assigned to names. 
They will be parametric values, but they will be values.
The λ-notation performs this task by preceding the function body with
a list of  variables, called %2⊗→lambda list↔←%*. The lambda list 
has been previously called the formal parameter list; either term is 
acceptable.
Each parameter in the lambda list is called a lambda variable (or 
a formal parameter).
The resulting construct is preceded by "λ[" and followed by "]".
Using the above example, the identifier %3f%* denotes exactly the
same LISP function as %3λ[[x;y]#x*y#+#y]%*. 
The λ-notation introduces nothing new as far as our intuitive binding and
evaluation processes are concerned; it only makes these operations more
clear.
To analyze these ideas a bit further, notice that %3λ[[x;y]#x*y#+#y]%1
is the "same" function as 
%3λ[[u;v]#u*v#+#v]%1. This means in effect that the formal  parameters
are "place holders" and can be  uniformly replaced with other identifiers.
Notice to that function names are also place holders.
.group;
.boxa
.BEGIN CENTERIT; SELECT 3;
←one[x] <= [x=0 → 1; %et%*  → one[x-1]]
.END
.pt2
.fp
is the same function as:
.pt2
.BEGIN CENTERIT; SELECT 3;
←fxy[x] <= [x=0 → 1; %et%*  → fxy[x-1]]
.END
.boxb
.apart
There are certain restrictions on the replacement of identifiers; the
precise description of that algorithm requires care. The implementation of
that algorithm will be part of this chapter.

One benefit of the
λ-notation is that we need not give explicit names to functions in order to
perform the evaluation. Evaluation of 
expressions involving such anonymous functions, also called %2open lambdas%1, is
within the province of LISP.
Currently, we will restrict our discussion to
λ-expressions which are  function constants, just like %3A%1
is an S-expr constant. Since a λ-expression is a constant, its value 
is itself.
LISP will
evaluate an application involving a λ-expression  in two stages;
first, it will bind the evaluated actual parameters
to the λ-variables, and then it will evaluate the function body. 

.GROUP;
Consider, for example:
.BOXA
←%3λ[[x;y] x%82%* + y][2;3] %1 
.BOXB
.FP
We associate %32%* with %3x%* and %33%* with %3y%* and evaluate the expression:
.BOXA
←%3x%82%* + y%1
.BOXB
.FP
This calculation will give %37%*.
.APART;
.GROUP;
To evaluate the more complex:
.boxa
.begin center
%3λ[[x] cdr[car[x]]][((A . B) . C)]%*
.end
.boxb
.fp
we bind %3x%* to the
S-expression %3((A#.#B).#C)%* and evaluate the function body. The 
 evaluation procedure first evaluates %3car[x]%* with  the current
binding of %3x%*; this result, %3(A#.#B)%*, is passed to %3cdr%*;
and that calculation finally returns %3B%*.
.APART;
.GROUP;
The λ-notation can be used anywhere LISP expects to find a function,  
for example:

.BEGIN tabit1(22);
.BOXA
\%3λ[[x] first[x]]
\   [λ[[y] rest[y]][(A B)]]%1
.BOXB
.END
.FP
This expression equivalent to writing:
.BOXA
←%3f[g[(A B)]]%*###  where %3f[x] <= first[x]## %*and## %3g[y] <= rest[y]%* 
.BOXB
.APART;
.GROUP;
.FP
Though the second form is perhaps easier for us to comprehend, the
first form %6is%* equivalent and will be acceptable to the evaluator.
In fact, the  evaluation of the  second formulation will 
effectively reduce to
the first formulation  on its way to final evaluation. 
.BOXA
←%3λ[[x] first[x]][λ[[y] rest[y]][(A B)]] = λ[[x] first[x]][(B)] = B%1
.BOXB
.APART;

LISP evaluation requires
care. For example   the LISP function %3λ[[x]2]%*  is %6not%1 
the constant function which always
gives value %32%*.
The evaluation of an expression  involving
this function requires the evaluation of the actual parameter associated with %3x%*.
That computation may not terminate. For example, consider %3λ[[x]2][fact[-1]]%* 
where %3fact%* is the LISP implementation of the factorial function given on
{yon(P20)}.

.GROUP;
Since we intend to include  λ-expressions in our language we must include
an %eR%*-mapping into S-expression form for them.
The character  λ  will be translated to %3LAMBDA%* and the formal parameters
will be translated into a list:

.BEGIN GROUP;centerit;
.BOXA
←%eR%f( %3λ[[x%41%*; ...; x%4n%*] %9x%*] %f)%3 = (LAMBDA (X%41%* ...  X%4n%*) %eR%f(  %9x%3 %f)%3)%1
.BOXB
.END
.APART

.BEGIN "XX9" CENTERIT;GROUP;
Here are some examples of %3λ%*-expressions and their %eR%*-translations:
.BOXA
←%eR%f( %3λ[[x;y] x%82%* + y] %f)%3  = (LAMBDA (X Y) (PLUS (EXPT X 2) Y))
.EQ1(5)
\%eR%f( %3λ[[x;y] cons[car[x];y]] %f)%3  = (LAMBDA (X Y) (CONS (CAR X) Y))
.END
.END "XX9"
.boxb

.GROUP;
To complete our introduction of λ-expressions,
our LISP syntax equations will  be augmented to  include:

.BEGIN TABIT1(14);GROUP;
.BOXA
<function>\::= λ[<varlist><form>]
.PT2
<varlist>\::= [<variable>; ... ; <variable>]  ⊗↓Recall that 
this use of ellipses means "zero or more occurrences of <variable>".←
.BOXB
.END
.APART;
.GROUP;
Besides giving a clear notation for  function definitions,  the λ-notation
is a useful computational device.
Consider the following sketch of a function definition:
.BOXA
←%3g <= λ[[x][%9p%*[lic[x]] → lic[x]; .... x ...]]%1 
.BOXB
.FP
where %3lic%* may be a %3l%*ong %3i%*nvolved %3c%*alculation, and
%9p%1 is a predicate.
.APART;
.GROUP;
We certainly must compute %3lic[x]%* %6once%*. But as %3g%* is defined,
we would compute %3lic[x]%* %6twice%* if %2p%41%1 is true: once
in the calculation of %2p%41%1, and once as %2e%41%1. Since 
both calculations of %3lic[x]%* will give the same value,⊗↓Our
current LISP subset has no side effects. That means
there is no way for a computation to affect its surrounding
environment. The most common construct which has a side-effect
is the assignment statement.←  this second calculation
is unnecessary. Instead, we could write:
.BOXA
←%3g <= λ[[x] f[lic[x];x]]%1
.PT2
.FP
where:←%3f <= λ[[u;v][%9p%*[u] → u; .... v ...]]%1
.APART;
.BOXA
.P170:
.FP
In this scheme %3lic%*   will   only be evaluated once; its value
will be passed into %3f%*.
This solution requires introduction of a new function name.
Using λ-expressions, in a style
called %2⊗→internal lambdas↔←%* we can improve %3g%* without 
adding any new function names to our symbol tables.

Replace the body of %3g%* with:
.BOXA
.FP
%2LAM←            %3λ[[y][%9p%*[y] → y; ... x  ...]][lic[x]]%1
.BOXB
.FP
Call this new function %3g%9'%1:
.BOXA
.FP
←%3g%9'%3 <= λ[[x]#λ[[y][%9p%*[y] → y; ... x ... ]][lic[x]]#] %1 
.BOXB
.FP
Now when %3g%9'%1 is called we evaluate the actual parameter, binding it
to %3x%*,  and evaluate  %2LAM%*. Evaluation of %2LAM%*
involves only one calculation of %3lic[x]%*, binding the result to
%3y%*. We then evaluate the body of the conditional expression as before.
If %2p%41%1 %6is%* true, then this definition of %3g%9'%1 involves
one calculation of %3lic[x]%* and two table look-ups (for the value of %3y%*),
rather than the two calculations of %3lic[x]%* in %3g%*.
More conventional programming languages can obtain the same effect as
this use of internal lambdas by assignment of %3lic[x]%* to a
temporary variable. We will introduce assignment statements in LISP in
{yonss(P37)}.⊗↓This technique is also related to the ideas of common sub-expression
recognition in compiling algorithms#({yonss(P258)}).← 
.END

.CENT(Problems);
.NL
1.##What is the difference between %3λ[[ ] x*y + y]%* and %3x*y + y%*#?


.END "LAMBDA"
.SS(Mechanization of Evaluation,,P6:)
.begin "mech"
%1
.FP
We first gave plausibility arguments for the existence of an evaluator for
LISP; 
and then picked a representation for LISP expressions; finally
we
introduced a precise notation for discussing functions.
It is now time to write an  evaluator for representations of LISP expressions.
The evaluator will be the final arbiter on the question of the
meaning of a LISP construct. The evaluator is thus a very important
algorithm. We will express it and its related functions in a  
representation-free form, but we will  keep
our Cambridge Polish 
representation in mind.

As we have discovered, the great progenitors ({yonss(P39)}) are evaluators 
for subsets of LISP.
With our symbol-table mechanism we could now extend those
algorithms to handle variable look-ups.
Rather than do this we will 
 make a total revision of the structure of the
evaluators. In making the revision, the
following points should be remembered:

.BEGIN GROUP;
.PT24
.NL
%21.%1##Expressions  to be evaluated  can contain variables, both simple
variables and variables naming λ-expressions. Therefore, evaluation must be done
with respect to an environment or symbol table. We wish to recognize other
 function names besides %3CAR, CDR, CONS, EQ,%* and%3 ATOM%* 
in our evaluator, but
explicitly adding  new definitions to the evaluator in the style of the
recognizers for the five primitives is not an attractive approach.
That scheme would require rewriting sections of the evaluator every time
a new definition was introduced. An alternative solution 
is to hold the definitions in a symbol table. Our symbol table should
hold the function definitions and the evaluator should contain the general
schemes for finding the definitions, binding variables to values, and
evaluating the function body. 
.APART;
.GROUP;
.NL
%22.%1##All %2function%* calls are to be evaluated "by-value." However, there are
some %2⊗→special forms↔←%*  which are not evaluated in the 
normal manner.  Conditional expressions, quoted expressions,
and lambda expressions are handled differently, and the evaluator will recognize
these constructs specially.
.PT18
.END
The primary algorithm in  the evaluator
will be named ⊗→%3eval%*↔←.
It will take two arguments; the first
will be  a representation of an expression to be evaluated, and the second
will be a representation of a symbol table. 
The evaluator will recognize numbers,
 and the
constants %3T%* and %3NIL%*, and if presented with a variable, will attempt to 
find the value of the variable in the symbol table using %3assoc%* ({yonss(P92)}).

%3eval%* will also recognize the special forms %3cond%* and %3quote%*. 
When %3eval%* recognizes
a ⊗→conditional expression↔← (represented by %3(COND ...)%* ), the body
of the ⊗→%3COND%*↔← will be passed to a subfunction named ⊗→%3evcond%*↔←. 
%3evcond%* embodies the conditional expression semantics as described on {yon(P40)}.
The representation,
%3(QUOTE#%9α%3)%1, signifies the occurrence of a constant, %9α%1, which is
simply returned.
Any other expression is a 
call-by-value application.
The argument-list evaluation is handled by %3evlis%* in the authorized
left-to-right ordering. This calculation is performed by recurring 
on the list representing the arguments.
Finally, we %2apply%* the function
to the list of evaluated arguments. 
This is done by the function %3apply%*.

With this introduction we will now write a more general evaluator
which will handle a larger subset of LISP than the %3tgm%*s.

.BEGIN SELECT 3;GROUP;TABIT2(11,40);
.FP
%1Here's the new %3eval%1:%3
.BOXA
eval <= λ[[exp;environ]
\[isconst[exp] → denote[exp];
\ isvar[exp] → lookup[exp;environ];
\ iscond[exp] → evcond[arg%4c%3[exp];environ];
\ isfunc+args[exp] → apply[\func[exp];
\\evlis[arglist[exp];environ];
\\environ] ]]
.BOXB
.END
.BEGIN SELECT 3;GROUP;TABIT1(20);
.FP
%1and:%*

lookup <=λ[[var;env] value[assoc[var;env]]]

denote <= λ[[exp]\[isnumber[exp] → exp;
\ istruth[exp] → exp;
\ isfalse[exp] → exp;
\ issexpr[exp] → rep[exp];
\ islambda[exp] → exp ]]

.END
.GROUP
.BOXB
.fp
%1where:%*

.BEGIN FILL;
.DEF
%3rep%1 knows how to extract the S-expr from the representation. In our scheme
the selector %3rep%1 is given by %3cadr%1.
.END
.FP
The other selectors, constructors and recognizers which relate this abstract
definition to our particular S-expression representation are grouped 
 on {yon(P108)}.
.APART;

.BEGIN SELECT 3;GROUP;TABIT1(15);
.BOXA
evcond <= λ[\[e;environ]
\[eval[ante[first[e]];environ] → eval[conseq[first[e]];environ];
\ %et%* → evcond[rest[e];environ] ]]
.END
.BEGIN SELECT 3;GROUP;TABIT2(24,36);
.GROUP
.FP
%1and,%*

.P191:
evlis <= λ[[e;environ]\[null[e] → ( );
\ %et%* → concat[\eval[first[e];environ];
\\evlis[rest[e];environ]] ]]
.BOXB
.END
.FP
The subfunctions, %3evcond%* and %3evlis%*, are simple.  %3evcond%1 appeared
before in %3tgmoafr%* in a less abstract form;
%3evlis%1 constructs a new list consisting of the
results of evaluating  the elements of %3e%* from left to right, using the
symbol table, %3environ%*, where necessary.
Since %3evcond%1 and %3evlis%1 are LISP functions, %6they%1 are subject to the 
left-to-right evaluation rule. Thus %3evlis%1 embodies the left-to-right rule.
If %3evlis%1 were evaluated under a right-to-left rule then %3evlis%1
would evaluate expressions in right-to-left order.
It is possible to write a version of %3evlis%1 which only depends on
being evaluated %2CBV%1, and which  does embody the left-to-right rule:

.BEGIN TABIT2(24,37);SELECT 3;group;
.BOXA
evlis <= λ[[e;environ]\[null[e] → ( );
\ %et%* → λ[[x] concat[x;evlis[rest[e];environ]]] 
\\[eval[first[e];environ]] ]]
.BOXB
.END


To continue,
the function ⊗→%3apply%*↔← takes three arguments: a representation of a function,
a representation of  the evaluated arguments,
and a representation of a symbol table. 
%3apply%* explicitly recognizes the representations of the five 
primitive functions %3CAR,
CDR, CONS, EQ, %*and%3 ATOM%*. If the function name is a variable,
the
definition is located in the symbol table by %3eval%* and applied to the arguments.
Otherwise the function must be a λ-expression.  Things now
get interesting; we must  evaluate the body of the
λ-expression after binding the formal parameters of the λ-expression
to the evaluated arguments.    We add variable-value
pairs to the front of the current symbol table. 
We will define a subfunction, %3mkenv%*, to
perform the binding;  then pass  the function
body and the new symbol table to %3eval%*. 
.BEGIN SELECT 3;GROUP;TABIT2(14,37);
.FP
%1Here is %3apply%*:%3
.BOXA
.P69:
apply <= λ[\[fn;args,environ]
\[iscar[fn] → car[arg%41%*[args]];
\ iscons[fn] → cons[arg%41%*[args];arg%42%*[args]];
\        ...                ... 
\ isvar[fn] → apply[eval[fn;environ];args;environ];
\ islambda[fn] → eval[\body[fn];
\\mkenv[vars[fn];args;environ]] ]]
.PT18
.END
.BEGIN SELECT 3;GROUP;TABIT3(15,27,35);
mkenv <= λ[[vars;vals;environ] pairlis[vars;vals;environ]]
.PT18
pairlis <= λ[[vars;vals;environ]
\[null[vars] → environ;
\ %et%* → concat[\mkent[first[vars];first[vals]];
\\pairlis[\rest[vars];
\\\rest[vals];
\\\environ]] ]]
.BOXB
.END


Some of the
 functions and predicates which will relate these abstract definitions to our
specific S-expression representation of LISP constructs are given below.

.BEGIN "yy" TABIT3(5,33,48);GROUP;SELECT 2;
.BOXA
.P108:
\Recognizers\\Selectors
.SELECT 3;
iscar <= λ[[x] eq[x;CAR]]\\func <= λ[[x] first[x]]
isSexpr <= λ[[x] eq[first[x];QUOTE]]\arglist <= λ[[x] rest[x]]
istruth <= λ[[x] eq[x;T]]\\body <= λ[[x] third[x]]
islambda <= λ[[x] eq[first[x];LAMBDA]]\vars <= λ[[x] second[x]]
isfun+args <= λ[[x] %et%3]\\args%4c%3 <= λ[[x] rest[x]]
\\\arg%41%3 <= λ[[x] first[x]]
\\\arg%42%3 <= λ[[x] second[x]]
\\\ante <= λ[[x] first[x]]
\\\conseq <= λ[[x] second[x]]
\\\rep <= λ[[x] second[x]]
.PT18
.EQ;
%2Constructor%1
.EQ
%3mkent <= λ[[x;y] cons[x;y]]%1
.END "yy"
.BOXB



Another application of the left-to-right property occurs 
within %3apply%*, in the symbol table
search and construction process. Notice that 
%3lookup%1 uses %3assoc%* to look from left to right
for the latest binding of a variable. Thus the function which %6augments%* the
table must add the latest binding to the %6front%*. New bindings
occur when the function 
%3mkenv%1, using %3pairlis%*,
builds an augmented symbol table with the λ-variables bound to their evaluated
arguments. The
functions %3lookup%1 and %3mkenv%1 operate together. We will see representations
of these functions other than %3assoc%1 and %3pairlis%1. The actual search  and
construction operations will change, but the critical relationship that %3mkenv%1
always builds a table compatible with the search strategy of %3lookup%1
will be maintained.

.P86:
To summarize then: the evaluation of an expression %3f[a%41%*;#...#;a%4n%*]%1,
where the %3a%4i%1's are S-exprs,
consists in  applying %3eval%* to the %eR%*-translation,
%3(%eR%f(%3#f#%f)%3#%eR%f(%3#a%41#%f)%3#...#%eR%f(%3#a%4n#%f)%3).%1
This behavior is again an example of the diagrams of {yon(P46)}. In its
most simple terms, we mapped LISP evaluation onto the LISP %3eval%* function;
mapped LISP expressions onto S-expressions; and executed %3eval%*. Notice
that in this case we do not reinterpret the output since the structure of the
representation does this implicitly. We have commented on the efficacy
of this already on {yon(P110)}. 

The specification of the evaluation of LISP
expressions using %3eval%* and %3apply%*
is one of the most interesting developments of computer science.

.CENT(Problems)
.NL
1.##Compare our version of %3eval%* and %3apply%* with the version given in 
⊗↑[McC#65]↑. 
Though the current version is much more readable, how much of it %6still%* depends
on the representation we chose? That is, how abstract is it really?
.NL
2.##Complete the specification of the selectors, constructors, and recognizers.
.END "mech"
.SS(Examples of %3eval%*,examples of %3eval%*)
.BEGIN "EXAM"
.FP
We will demonstrate the inner workings of the evaluation  algorithm
on a couple of samples and will describe the flow of control in the
execution in a couple of different ways. 
The examples will be done in terms of the image of the %eR%*-mapping
rather than being done abstractly. We do this since the structure of an
actual LISP evaluator will use this representation.⊗↓Recall that we will 
be programming in the %eR%*-image.← 
It is important that
you diligently study the sequence of events in the execution
of the evaluator. The process is detailed, but it must be done at least once.

Let's evaluate %3f[2;3]%* where %3f <= λ[[x;y] x%82%* + y].%1
That is, evaluate:

.BEGIN TURN OFF "{,}";
.BOXA
.ONCE CENTER
%3eval[ %eR%f(%3 f[2;3] %f)%3; %eR%f(%3{ <f, λ[[x;y] +[↑[x;2]; y]]> }%f)%3]%1 
.BOXB
.END
.FP
After appropriate translation this is equivalent to evaluating:
.BOXA
.ONCE CENTER
%3eval[(F 2 3); ((F . (LAMBDA (X Y) (PLUS (EXPT X 2) Y))))]%*
.BOXB
.FP
%2Notes:%*

.BEGIN GROUP;
.PT24
.NL
%21.%*  %3((F . (LAMBDA (X Y) ... ))) = ((F LAMBDA (X Y) ... )) %*
This is mentioned because most LISP implementations will print the latter
even if you write the former.
.APART;
.GROUP;
.NL
%22.%*  Since the symbol table  %3((F ...))%* occurs so frequently in the following
trace, we will abbreviate it as %2st%*. We have no mechanism yet
for permanently increasing the repertoire of known functions.  We must
therefore
resort to subterfuge and initialize the symbol table to get 
%3f%* defined.
.NL
.GROUP
%23.%*  For this example we must assume that + and ↑ (exponentiation) are known functions.  Thus
%3apply%* would have to contain recognizers for %3PLUS%* and %3TIMES%*:
.BEGIN TABIT2(10,28);
.SELECT 3;
.BOXA
\. . . atom[fn] → [\isplus[fn] → +[arg%41%*[args];arg%42%*[args]];
\\isexpt[fn] → ↑[arg%41%*[args];arg%42%*[args]];
\\	         . . . ]
\      . . .
%1
.END
.END
.BEGIN NOFILL;KRK; TURN ON "\";tabS 5,13,15,21,25,35,43
.P129:
.GROUP
So %3eval[(F 2 3);%2st%3]
\= apply[\func[(F 2 3)]; 
\\\evlis[arglist[(F 2 3)];%2st%3];
\\\%2st%3]

\= apply[F;evlis[(2 3);%2st%3];%2st%3]
\= apply[F;(2 3);%2st%3]

\= apply[\eval[F;%2st%3];
\\\(2 3);
\\\%2st%3]
\= apply[\(LAMBDA (X Y) (PLUS (EXPT X 2) Y)); 
\\\(2 3);
\\\%2st%3]

\= eval[\body[(LAMBDA (X Y) (PLUS (EXPT X 2) Y))];
\\mkenv[\vars[(LAMBDA (X Y) (PLUS (EXPT X 2) Y))];
\\\\(2 3);
\\\\%2st%3]]

\= eval[\(PLUS (EXPT X 2) Y);
\\pairlis[(X Y);(2 3);%2st%3]]

\= eval[\(PLUS (EXPT X 2) Y);
\\((X . 2)(Y . 3)(F LAMBDA (X Y) ...))]

\= apply[\PLUS; 
\\\evlis[((EXPT X 2) Y);((X . 2)(Y . 3)..)];
\\\((X . 2)...)]
.APART
.GROUP

.FP
%1Let's do a little of:%3  evlis[((EXPT X 2) Y);((X . 2)(Y . 3)...)]
.PT2;pt2
\\\\\= concat[\eval[(EXPT X 2);((X . 2)(Y . 3) ...)];
\\\\\\evlis[(Y);((X . 2) ...)]]
\\\\\= concat[\apply[\EXPT;
\\\\\\\evlis[(X 2);((X . 2)...)];
\\\\\\\((X . 2) ...]
\\\\\\evlis[(Y); ...]]

\\\\\= concat[\apply[\EXPT;
\\\\\\\(2 2);
\\\\\\\((X . 2);
\\\\\\\...];
\\\\\\evlis[(Y); ...]]

\\\\\= concat[\↑[arg%41%*[(2 2)];arg%42%*[(2 2)]];
\\\\\\evlis[(Y); ... ]]

\\\\\= concat[↑[2;2];evlis[(Y); ... ]]
\\\\\= concat[4;evlis[(Y);((X . 2)(Y . 3) ....)]]
\\\\\= concat[4;concat[eval[Y;((X .2) ...)]; evlis[( );(( ...))]]]
\\\\\= concat[4;concat[3;( )]]
\\\\\= (4 3)%1
.APART
.GROUP;

Now back to %3apply%1:
.boxb
%3
\= apply[\PLUS;
\\\(4 3);
\\\((X . 2) (Y . 3) ... )]

\= +[4;3]
\= 7%1
.APART
.END
.BOXB
.FP
It should now be clear that %3eval%* does 
perform as you would expect, at least for this example.  It is not clear that a
simpler scheme might not do as well.  In particular, the complexity
of the symbol table mechanism which we claimed was so important
has not been exploited. The next example will  show that a
scheme like ours is necessary to keep track of variable bindings.
.GROUP
.FP
Let's sketch the evaluation of %3fact[3]%* where:
.BOXA
.ONCE CENTER
%3fact <= λ[[x][x = 0 → 1; %et%* → *[x;fact[x-1]]]]%1
.BOXB
.P42:
.FP
that is, %3eval[(FACT 3);%2st%3] %1where %2st%1 names the initial symbol table:

.BEGIN GROUP;SELECT 3; TABIT3(13,39,53);
.BOXA
((FACT .\(LAMBDA (X) (COND\((ZEROP X) 1)
\\(T (TIMES\X 
\\\(FACT (SUB1 X))))))))%1⊗↓We have split the %3COND%1 across several
lines in an indented fashion to improve readibility. Such techniques are common
in LISP. The idea is called "pretty#printing" and is discussed further on {yon(P245)}
and in {yonss(P226)}.← 
.BOXB
.END
.APART
.FP
In this example we will assume that the binary function  *, the 
unary predicate  %3zerop#<=#λ[[x]#x#=#0]%* and unary function  
%3 sub1#<=#λ[[x]#x-1]%* are known and are 
recognized in the evaluator as %3TIMES, ZEROP%* and %3SUB1%* respectively.

.BEGIN NOFILL;KRK;TURN ON "\";TABS 10,19,20,26
.GROUP
.BOXA
%1Then%3 eval[(FACT 3);%2st%3]
\= apply[\FACT;
\\evlis[(3);%2st%3];
\\%2st%3]
\= apply[\(LAMBDA (X) (COND ...));
\\(3);
\\%2st%3]
\= eval[(COND ((ZEROP X) 1) (T ( ...)));((X . 3) . %2st%3)]
\= evcond[\(((ZEROP X) 1) (T (TIMES X (FACT (SUB1 X)))));
\\\((X . 3) . %2st%3)]
.PT2
.APART
.GROUP;
%1Now, let %2st1%* be%3 ((X . 3) . %2st%3)  
.PT2
\= eval[(TIMES X (FACT (SUB1 X))); %2st1%3]
\= apply[\TIMES;
\\evlis[(X (FACT (SUB1 X))); %2st1%3];
\\%2st1%3]
\= apply[\TIMES;
\\concat[\3;
\\\\evlis[((FACT (SUB1 X))); %2st1%3]];
\\%2st1%3]
.END

.BEGIN NOFILL;KRK;TURN ON "\";TABS 5,15,25,27,36
.GROUP;
.BOXA
%1Now things get a little interesting inside %3evlis%1:
.pt2
.SELECT 3;
\evlis[((FACT (SUB1 X)));%2st1%3]
\\= concat[\eval[(FACT (SUB1 X)); %2st1%3];
\\\( )]
\\%1 and %* eval[(FACT (SUB1 X));%2st1%3]
\\\\= apply[\FACT;
\\\\\evlis[((SUB1 X));%2st1%3];
\\\\\%2st1%3]
\\\\= apply[FACT; (2);%2st1%3]
\\\\= apply[\(LAMBDA (X) (COND ...));
\\\\\(2);
\\\\\%2st1%3]

\\\\= eval[(COND ((ZEROP X) 1) ...));((X . 2) . %2st1%3)]
\\\\ . . .
.BOXB
.APART
.FILL
%1
.FP
Within this latest call on %3eval%* the symbol-table-searching function,
%3lookup%*, will find the pair %3(X#.#2)%* when looking for the value of %3x%*. This is
as it should be.  But notice also that the older binding, %3(X#.#3)%*, is still 
around in the symbol table %2st1%1, and will become accessible once we complete
this latest call on %3eval%*.
It will become accessible because this earlier manifestation of the table was
saved by the λ-binding process as we entered the inner call on %3eval%1; as we
leave this inner evaluation, the previous incarnation of the table is restored.
.GROUP

As the computation continues, the current symbol table appears as follows:
.NOFILL

.BEGIN TURN ON "←";
%3
.BOXA
←((FACT LAMBDA (X) (COND ...))) = %2st%3 
←((X . 3) . %2st%3) = %2st1%3 
←((X . 2) . %2st1%3) = %2st2%3 
←((X . 1) . %2st2%3) = %2st3%3 
←((X . 0) . %2st3%3) 
%1
.BOXB
.END
.FILL
.APART
.FP
Thus each new level of the table builds on the prior table; each prior table
is saved by the following line from %3apply%1 ({yon(P69)}):

.BEGIN CENTERIT;SELECT 3;
.BOXA
←islambda[fn] → eval[body[fn];mkenv[vars[fn];args;environ] 
.BOXB
.END
.FP
The call on %3eval%1 is performed with the augmented table; when we leave that
inner %3eval%1 we return to an environment which contains the prior table. 

Using %3mkenv%* to concatenate the new 
bindings onto the front of the symbol table as we call %3eval%*,
generates the required environment.
The tricky part occurs  when we leave that particular call on
%3eval%*; the old table is automatically restored by the recursion
mechanism.  That is, concatenating
 things onto the front of a table doesn't change the table, but if we
call %3eval%* or %3apply%* with a symbol table of say:
.BOXA
.ONCE CENTER;
%3concat[(X . 2);concat[(X . 3); %2st%3]] %1
.BOXB
.FP
then in %6that%* call on  %3eval%* or %3apply%* we have access to  %32%1
as the value of %3x%1, rather than %33%1.

In this representation,
the search function  %3lookup%1  always proceeds from left to right through
the table and, since the table entry function  %3mkenv%*  always adds  pairs
onto the left of the table before %3eval%* is called, we will get the expected
binding of the variables.

.P212:
The structure of %3mkenv%1 should be analyzed further: it takes a formal
parameter list, an evaluated actual parameter list, and an environment, as
its arguments; it  allocates a new block to contain the name-value pairs and
proceeds to send each name-value pair to its proper slot in the block. The value 
of %3mkenv%1  is the newly constructed environment formed by
linking the new block onto the front of the old environment. 
It turns out that %3pairlis%1
is able to combine the action of making the new block and filling the slots.
.BEGIN GROUP;
A more accurate picture of the abstract behavior of %3mkenv%1 is:
.TABIT3(37,51,57);SELECT 3;
.P213:
.BOXA
mkenv <= λ[[vars;vals;env] mkenv%9'%3[vars;vals;alloc[vars];env]]
.PT18
mkenv%9'%3 <= λ[[vars;vals;block;env]\[null[vars] → link[block;env];
\ %et%3 → mkenv%9'%3[\rest[vars];
\\rest[vals];
\\send[\first[vars];
\\\first[vals];
\\\block];
\\env] ]]]
.BOXB
.END

.BEGIN CENTERIT;group
Our current implementation of %3pairlis%1 is equivalent to:
←%3alloc <=λ[[x] ( )] ⊗↓%3alloc%1 is defined as a unary function even though
its argument is ignored here. This generality is in anticipation of future
binding implementations.←
.BOXA
←%3send <= λ[[var;val;block] concat[mkent[var;val];block]]
.PT18
←link <= λ[[block;env] append[block;env]]
.BOXB
.END
The computational behavior of %3pairlis%1 is slightly different: here 
the
name-value pairs are added to the environment in an order
reverse to that used in %3pairlis%1. Since
the variables in the λ-list must be distinct from one another,
this alternative
environment is equivalent to the previous one.


.END

.<<the |   | symbol table >>
.P43:
Symbol table manipulation is very important, so let's look at it
again in a slightly different manner.
In this example,
expressions and table entries will be written more informally. 
Since the evaluator is operating on the list representation of expressions
we should continue to present these arguments to %3eval%1 as lists.
However, the object being represented might be more understandable
and readable⊗↓Readability of LISP expressions is a subject of heated 
between LISP users and non-users. Since
we program using the list representation there is  an initial period
in which the representation is "difficult to read". However that phemononon is
short lived; the regularity of LISP expressions, the minimality of syntax, 
the use of
formatting programs called "pretty printers", and several abbreviational devices
soon overcome any supposed disadvantages. This text presents LISP expressions
in the meta-language since we wish to stress the notions of representation
independence, rather than LISP's programming behavior.←
than the representation of that object. Thus, initially, we
will write %eR%f(%9x%f)%1  
rather than the explicit %eR%1-image of %9x%1; 
for example, write %eR%f(%3fact[3]%f)%1
rather than %3(FACT#3)%1.
Later we will simply write %9x%1 where no confusion is
likely.
With similar motivation,
we represent the symbol table between vertical
bars, "|", in such a way that if a table, t%41%*, is:
.BEGIN TABIT2(10,17);GROUP
.BOXA
\|  b%4n%*\|
\|   ...\| then %3concat%*ing a new element, b%4n+1%* onto t%41%* gives:
\|  b%41%*\|
.PT24
\|  b%4n+1%*\|
\|  b%4n%*\|
\|   ...\|
\|  b%41%*\|
.BOXB
.END
.FP
The elements of the table should also be presented  as %eR%1-images,
 but we will represent the entries in a more transparent form.
For example:


.SELECT 3

.BEGIN NOFILL;TABS 1,46,62,72;TURN ON "\";select 3;
.KRK
.BOXA
eval[%eR%f(%3fact[3]%f)%3;###### | fact : λ[[x][x=0 → 1;%et%* → *[x;fact[x-1]]]] | ]

.GROUP
\= eval[%eR%f(%3[x=0 → 1; %et%* → *[x;fact[x-1]]]%f)%3;\|x : 3 \|  ]
\\| fact : λ[ ... ]\|    

.APART
.GROUP
\= *[3;eval[%eR%f(%3[x=0 → ...]%f)%3; \|    x : 2\|  ]
\\|    x : 3\|
\\| fact : λ[ ... ]\|   


.APART
.GROUP
\= *[3; *[2;eval[%eR%f(%3[x=0 → ...]%f)%3;\|    x : 1\|  ]
\\|    x : 2 \|
\\|    x : 3\|
\\| fact : λ[ ... ]\|   


.APART
.GROUP
\= *[3; *[2; *[1;eval[%eR%f(%3[x=0 → ...]%f)%3;\|    x : 0 \|  ]
\\|    x : 1\|
\\|    x : 2\|
\\|    x : 3\|
\\| fact : λ[ ... ]\|    

.APART
.GROUP
\= *[3; *[2; *[1;1]]]  %1with:%*\|     x : 1\|  ]
\\|     x : 2\|
\\|      ... \|

.APART
.GROUP
\= *[3; *[2;1]]         %1with:%*\|     x : 2\|  ]
\\|      ...\|

.APART
.GROUP
\= *[3;2]                %1with:%*\|     x : 3\|  ]
\\|      ...\|

\= 6                      %1with:%*\| fact : λ[ ... ]\|

= 6
.END
.BOXB
%1
.FP
Notice that after we went to all the trouble to save the old values
of %3x%* we never had to use them.  However, in the general case of 
recursive evaluation we must be able to save and restore the old values
of variables.
For example, if we had defined %3fact%1 as:
.BEGIN CENTER;SELECT 3;
.BOXA
 fact <= λ[[x][x=0 → 1; %et%* → *[fact[x-1];x]]],
.BOXB
.END
.FP
then we %6would%1 have to access the old binding  of %3x%1.

For further example, recall the definition of %3equal:
.BEGIN NOFILL TURN ON "\";TABS 18;
.KRK
.GROUP
.BOXA
%3
equal <= λ[[x;y]\[atom[x] → [atom[y] → eq[x;y]; %et%* → %ef%*];
\ atom[y] → %ef%*;
\ equal[car[x];car[y]] → equal[cdr[x];cdr[y]];
\ %et%* → %ef%*]]
.BOXB
.APART
.FP
%1If we were evaluating:%3
.CENTERIT
.BOXA
←equal[((A . B) . C);((A . B) . D)],
.BOXB
%1
.FILL
.FP
then, reading across the page, our symbol table structure would  change as follows:
.END
%3

.BEGIN NOFILL;TABS 10,30,42,62;TURN ON "\";
.KRK
.GROUP

\|equal : λ[[x;y] ...]\| ==>\|x : ((A . B) . C)\| ==>
\\\|y : ((A . B) . D)\|
\\\|equal : λ[[x;y] ... ]\|
.APART
.GROUP

\|   x : (A . B)\|\|       x : A  \|
\|   y : (A . B)\|\|       y : A\|
\| x : ((A . B) . C)\|  ==>\|    x : (A . B)\| 
\| y : ((A . B) . D)\|\|    y : (A . B)\| ==>
\|equal : λ[[x;y] ... ]\|\| x : ((A . B) . C)\|
\\\| y : ((A . B) . D)\|
\\\|equal : λ[[x;y] ... ]\|
.APART
.GROUP

\|       x : B\|\|        x : C\|
\|       y : B\|\|        y : D\|
\|    x : (A . B)\|\|  x : ((A . B) . C)\| ==>
\|    y : (A . B)\| ==>\|  y : ((A . B) . D)\|
\| x : ((A . B) . C)\|\|equal : λ[[x;y] ... ]\|
\| y : ((A . B). D)\|
\|equal : λ[[x;y] ... ]\|


.CENTERIT
←|equal : λ[[x;y] ... ] |
.END
.BOXB
%1
.FP
This degree of complexity is necessary, for while we are evaluating
%3equal[car[x];car[y]]%*, we rebind %3x%* and %3y%* but we must save the old 
values of %3x%* and %3y%* for the possible evaluation of %3equal[cdr[x];cdr[y]].%*
It is %6not%1 clear that this implementation is optimal. The search
for  the values of %3x%1 and %3y%1  is short, but the evaluation of any 
subexpressions
involving %3equal%1 must retrieve the definition of %3equal%1. That search
is proportional to the depth of the initial arguments to %3equal%1.

.P93:
Before continuing, we should examine %3eval%* and %3apply%* to see how they
compare with our previous discussions of LISP evaluation.
The spirit of call-by-value and conditional expression evaluation is maintained.
λ-binding seems correct, though our current discussion is not complete.
At least one preconception is not maintained here. Recall the discussion on
{yon(P95)}. We wanted n-ary functions called with exactly n arguments. An
examination of the structure of %3eval%* and %3apply%* shows that
if a function expecting %6n%* arguments is presented with fewer, then
the result is undefined; but if it is given %6more%* arguments than necessary
then the calculation is performed. For example:

.BEGIN TABIT1(19);GROUP;SELECT 3;
.BOXA
eval[(CONS (QUOTE A) (QUOTE B) (QUOTE C));NIL] 
\%1reduces to %3  eval[(CONS (QUOTE A) (QUOTE B));NIL] 
\%1reduces to %3 (A . B)
.BOXB
.END

This example shows one of the pitfalls in defining a language by an evaluator.
If the intuitions of the language specifiers are faulty or incomplete
then either we must maintain that faulty judgement,
or we must lobby for a "revised report".⊗↓For example the LISP#1.6 system
(⊗↑[Qua#72]↑) gives %3(A#.#A)%1 for %3cons[A]%1; the MacLISP system (⊗↑[Moo#74]↑)
gives %3(A#.#%1"missing-arg"%3)%1; and InterLISP (⊗↑[Int#75]↑) gives
%3(A)%1.← 

The definition of a language by an evaluator written in that language
is subject to other criticisms. The troublesome areas of our description of
LISP's evaluation included λ-binding, calling styles in general and call-by-value
in particular, and left-to-right order of evaluation. We wrote %3eval%1 to
explicate the meaning of these constructs, yet within %3eval%1 we often relied
on exactly these constructs to convey our intent. Now, our description
in not entirely circular; %3eval%1 does convey much of our intention to
the reader, but the discussion of %6how%1 these constructs operate
is either implicit or is explained by using the same kind of constructs.
In gaining a clearer understanding of what LISP constructs mean, %3eval%1
is exemplary. Indeed many of the details of how these constructs work
are irrelevant to such an understanding. When we attempt to
implement a language feature we cannot assume the existence of that
feature; the implementation must be prepared from a combination of more primitive
components. As we proceed through the text we will introduce
the mechanisms which are necessary to  implement LISP
and, indeed, implement the constructs of most other languages. In {yonss(P187)} we
give several alternative algorithms for %3eval%1. The
algorithms  will evolve to an %3eval%1
which makes explicit most of the mechanisms we need. In {yonsec(P188)}
we will begin to discuss efficient representations for LISP's data structures,
control structures, and primitive operations. 
The remainder of the current chapter will explicate further features of  LISP
 in preparation for that discussion.

.CENT(Problems)
.NL
1.##Which  parts of the evaluator   allow the  evaluation  of functions
applied to too many arguments? 
.NL
2.##Find other anomalies in the evaluator. That is, find places
where unexpected results are obtained?
.END "EXAM"
.SS(Variables,variables,P135:)
.BEGIN "VARS"
.BEGIN TURN ON "#";
.FP
Let's look more closely at λ-binding in %3eval%*. 
The scheme presented seems reasonable,
but as with "%3cons[A;B;C]%*", there may be more expressed here 
than we anticipated.

If we asked %3eval%*
to compute %3f[2]%*, given a representation for %3f#<=#λ[[x]#x#+#y]%1 
but no  representation for  the value of %3y%1
it would complain. It  would find %3f%1,
bind  %32%* to %3x%*,
and  begin the evaluation of the body of %3f%1. It would find %3x%1's value,
but  it would find no value for 
%3y%*. However, if we asked it to evaluate the form %3λ[[y]#f[2]][1]%*
it %6would%* work. It would find the value of %3y%* to be 
%31%* and would get a final answer of %33%*. You should convince
yourself of this assertion.

Within the evaluation of %3f[2]%* in %3λ[[y]#f[2]][1]%1 
the variable %3y%* has a different character from that of %3x%*.
The value of %3x%1 is found within the latest λ-binding, whereas %3y%1
was bound in a dynamically surrounding λ-binding. That is, the λ-expression
which bound %3y%1 took effect  before the binding of %3x%1 and is still in effect
when the binding of %3x%1 is made. We do have access to %3y%1's binding in 
this case; the %3lookup%1 routine will locate %3y%1's value.
There is a third kind of name-value association present in these examples:
we expect that the symbol "+" is recognized during the evaluation as denoting
a procedure for computing the sum of two numbers.  In previous discussions
we have assumed that "+" was  pre-defined inside %3apply%1  and therefore
explicitly recognized. Finally, in the first example, a fourth kind of
variable usage occurred. The variable %3y%1 had no associated value when 
the computation expected one. In this section we wish to examine these
properties of variables.

The implementation of λ-bindings  described in
%3pairlis%1 ({yon(P191)}) is slightly misleading. There, the new λ-bindings
are %3concat%1-ed onto the front of the existing table. They go on
in a one-at-a-time fashion even though they are to be thought of as
a logical unit: at the language level they all go on together, and
they all come off together. It is the structure of this table
which we should also examine. To these ends we now introduce some terminology.


Consider the evaluation of the expression:

.BEGIN CENTERIT;SELECT 3;
.BOXA
←λ[[y] equal[λ[[x] cons[x;y]][(A . B)];x]][A]
.BOXB
.END
.FP
in an environment where the definition
of %3equal%1 is known.

We evaluate the main argument %3A%1, and  perform the λ-binding of %3A%1
to %3y%1. This operation of λ-binding creates what we call 
a %2⊗→local symbol table↔←%1 and the variables bound in that local 
table are called
%2⊗→local binding↔←s%1 for the body of the λ-expression. 
We now begin the evaluation of the arguments
to %3equal%1. The first argument is itself an expression requiring λ-binding.
We evaluate it's argument and bind %3(A#.#B)%1 to %3x%1. 
This creates a local binding
for %3x%1. In the process of making %3x%1 local what happens to %3y%1?
Notice that the binding process has not made %3y%1 inaccessible: we
can  compute %3cons[x;y]%1 even though %3y%1 is not local. Variables like %3y%1
which are accessible, but not local, we call %2⊗→non-local↔←%1 variables.
Thus both %3y%1 and %3cons%1 are non-local variables in our evaluation
of %3cons[x;y]%1. There is a further distinction between %3y%1 and %3cons%1:
We expect %3cons%1 to be  a predefined function; indeed %3cons%1 has not been
λ-bound any where in our computation. Variables like %3cons%1 we will call
%2⊗→global variable↔←s%1. 

Global variables
 include predefined function names, %3car%1, %3cdr%1, etc, and
variables like %3t%1 and %3nil%1.
 A useful interpretation of global
variables is that they are bound in the initial symbol table, also
called the %2global table%1.⊗↓This analogy
breaks down somewhat in that usual implementations of LISP allow this global table
to be augmented; for example, by function definitions using a version of "<=".
Thus the global table can be enlarged whereas
a true λ-binding involves a fixed number of variables.← 
Non-local variables which are λ-bound
somewhere in the symbol table we call 
%2⊗→free variable↔←s%1, and variables which have %2some%1 accessible binding
at the current point in the computation are called %2⊗→bound variable↔←s%1.⊗↓Our 
notion of free
and bound variables has a decidedly computational flavor, in contrast
to the mathematical definitions of "free" and "bound" given on {yon(P254)}.
For example a variable may be both free and bound in our terminology.← 

Finally the first argument to %3equal%1 is evaluated giving %3((A#.#B)#.#A)%1.
As we complete that evaluation the local binding for %3x%1 becomes   
inaccessible, and
%3y%1 becomes local again. We examine the second argument to %3equal%1, 
which is %3x%1,
and now find there is  no binding for that  variable. Variables which have no
binding of any kind at the time we ask for a value 
are called %2⊗→unbound variable↔←s%1. The local, free, and global variables
make up the class of %2⊗→bound variable↔←s%1.

For a computation to be
meaningful, each variable which that computation references must be bound 
 when we ask for its value. The computation of our current example
would fail; 
it would fail even before we
asked for the definition of %3equal%1
since we are doing call-by-value. One of our tasks will be to 
discuss where definitions such as that for %3equal%1 should be kept.
.GROUP;
Here is a diagram of our characterization of variables:

.BEGIN SELECT g;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
                            ∞1variables∞*
                               ~	
                       ⊂ααααααα∀ααααααα⊃
  	               ~               ~
                     ∞1non-local∞*          ∞1local∞*
                       ~ 
                    ⊂αα∀ααααααπααααααααααα⊃
                    ~         ~           ~
                   ∞1free∞*      ∞1global∞*      ∞1unbound∞*
      
.BOXB
.END
.APART
.FP
Notice that a variable which is initially global may become 
local and then free by virtue
of  λ-bindings.

The binding strategy for local variables is reasonably
uniform in programming languages: bind some form of the actual
 parameters⊗↓The parameters may either be evaluated or unevaluated,
however.← 
to the formal parameters and evaluate the body of the
definition.
One of the difficulties  in programming languages
is deciding  what value to associate with a non-local variable.
In LISP, it is clear %6how%* values get associated; it happens through  λ-binding 
or by virtue of an initial entry in the symbol table.
The scheme which LISP uses for discovering the value of any variable is to
proceed linearly down the symbol table, looking for the %6latest
active%* binding.
This scheme is called %2⊗→dynamic binding↔←%*. It  %6usually%* results
in uncovering the value that is expected; but not always as we will see in 
{yonss(P76)}.
Conceptually, the dynamic binding scheme corresponds to the physical
replacement of the function call with the function body and then an
evaluation of the resulting expression. 
Free variables whose bindings are determined dynamically are called
%2⊗→fluid variable↔←s%1. 

In review, the evaluation of a typical function-call will involve 
the evaluation  of the arguments, the binding of the λ-variables
to those values, the addition of these new bindings to the front of the 
symbol table,
and finally the evaluation of the body of the function.
That segment of the symbol table which we have just added by the λ-binding will be called
the %2local symbol table%* or local environment. The variables
which appear in that segment are the local variables.
The remainder of the symbol table makes up the %2non-local table%*.
Variables which appear in the global table but not in any local table
are the %2⊗→global variable↔←s%*.
Free variables are bound somewhere between the local table and the global table.
Variables which are local to a form-evaluation are those which  were
present in the  λ-binding.
We first wish to develop a useful notation for describing
bindings before delving further into the intricacies of binding strategies.
That discussion will be the content of {yonss(P134)}.
.END

.BEGIN GROUP;

.CENT(Problems)
.NL;
1.##Write a LISP predicate, %3non <= λ[[x;e] ... ]%*, which will give %et%*
just in the case that %3x%* and %3e%*  represent a variable and a λ-expression
respectively, and %3x%* is non-local to %3e%*.
.nl
2.##Give an example showing that the phrase "latest binding"
is not a proper characterization of dynamic binding.
.END
.END "VARS"
.SS(Environments and Bindings,,P77:)
.BEGIN "ENVS"
.FP
This section will introduce one more notation
for describing symbol tables or environments. This notation, due to
J. Weizenbaum#(⊗↑[Wei#68]↑), only shows the abstract structure 
of the symbol table manipulations
during evaluation. Its simplicity will be of great benefit when we introduce
the more complex binding schemes necessary for function-valued functions in
{yonss(P76)}.

In the previous discussions it has been sufficient
to simply think of a symbol table as a sequence of pairs; each pair was a  variable
and its associated value. This sufficed because we dealt only with
λ-variables; we ignored the possibility of free variables. 
As long as we added the λ-bindings to the
%6front%* of the sequence representing the symbol table we showed that
expected evaluation would result. Local values were found in the table;
global values were found by explicit recognizers in %3eval%1 and %3apply%1.
With the advent of free variables, however, it 
will be necessary  to examine the structure of environments more closely.
We will describe our environments in terms of a local symbol table 
augmented by a description of where to look for the non-local values.

Instead of having one amorphous sequential symbol table, we
envision a  sequence of tables. One is the local table, and its 
successor in the sequence is the previous local table.  The
information telling where to find the previous table is called the
%2⊗→access chain↔←%* or %2⊗→access link↔←%1.
Thus if tables are represented by E%4i%1 and the access link
by %d→%* then we might represent a symbol table as:

.BEGIN CENTERIT;
.BOXA
←%3(%1E%4n%d → %1E%4n-1%d → %1 ...%d→ %1E%41 %d→%1 E%40%3)
.BOXB
.END
.FP
where %1E%4n%1 is the local or current segment of the table.
We reserve E%40%1 to name the global table.

LISP  finds local bindings in the local
table and uses the access chain to find bindings of non-local variables.
If a variable is not found in any of the tables, then it is unbound.


.BEGIN TABIT2(36,40);GROUP;

An environment will be described as:
.BOXA
\\%2Form%*
\\E%4local%*
\  \| E%4i%*
\_________
\var\| value
\%3v%41%1\| %2val%41%1
\%3v%42%1\| %2val%42%1
\   . . .
\%3v%4n%1\| %2val%4n%1
\\|
.BOXB
.END
.FP
%2Form%* is the current form being evaluated.
E%4local%* is the name of the current environment or symbol table. 
Let %3x%* be a variable appearing in %2Form%*. If %3x%* is not found
among the %3v%4j%1's,
then entries in the table named E%4i%* are examined.
 If %3x%1 is not found
in E%4i%* then the environment mentioned in the upper right-hand quadrant
of E%4i%* is searched. The search will terminate if %3x%1 is found as a %3v%4j%1;
the value of %3x%1 is  the corresponding %2val%4j%1.
If  %3x%* is not found  in a local table, and the symbol "/" appears in 
the right-hand quadrant, then %3x%* is unbound.


The notation is used as follows: when we begin the evaluation of a
form, the initial table E%40%* is
set up with "/" in its access field. 
The execution of a function definition, say %3f#<=#λ[[x;y]#x%82%*#+#y]%1, will
add an appropriate entry to the table, binding %3f%* to its lambda 
definition.⊗↓Note that we really mean "representation of lambda definition".← 
Now, consider the evaluation of the form %3f[2;3]%*.
When the λ-expression is entered, i.e.,
when we bind the evaluated arguments (%32%* and %33%*) to the 
λ-variables (%3x%* and %3y%*), a new local table (E%41%*) is set up
with an access link to E%40%*.
Entries reflecting the binding of the λ-variables are made in E%41%* and
evaluation of the λ-body is begun. 

.BEGIN TURN ON "\";NOFILL;TABS 5,8,11,29,32,47,49,52,57,60,73;
.KRK
.GROUP
The flow of symbol table creation is:
.BOXA
\\%3f[2;3]\\x%82%* + y%1
\\E%40%*\\\E%41%*\\\E%40%*
\  \| /\      \\| E%40%*\\  \| /
\\______  =>\______  =>\______  %1####return with value %37%1 
\ %3f\| λ[[x;y] x%82%* + y]%1  \%3 x\| 2\  \f\| λ[[x;y] ... ]
\\\\ y\| 3%1
.BOXB
.FP
Compare this sequence to the example on {yon(P129)}.
.END
.BEGIN GROUP;
The sequence of tables corresponds to the evaluation sequence:
.BOXA
.BEGIN CENTERIT;GROUP;turn off "{","}";
←%3eval[%eR%f( %3f[2;3] %f)%3; %eR%f( %3{<f , λ[[x;y] x%82%* +y]>} %f)%3]
←↓
←%3eval[%eR%f( %3x%82%* + y %f)%3; %eR%f( %3{<x, 2>, <y, 3>, <f , λ[[x;y] x%82%* +y]>} %f)%3]
←↓
←%37%1
.BOXB
.END
.END
.FILL;

You should realize that the Weizenbaum environments are just another
abstract data structure  with associated constructors, selectors, and
recognizers. They may be expressed as LISP data structures without much
difficulty. The only difference here is that the environments happen to
be more meaningful when described graphically  than if they were
specified by their manipulating functions. 
See the problem on {yon(P223)}.
Graphical representations
and languages are an important tool in data structure programming;
we will say a bit more about   this in {yonss(P275)}.
.<<RED'S FACT>>
.GROUP
The execution of %3fact[3]%* on {yon(P42)} results in a more interesting
example. The following discussion should be read in conjunction with that
description.⊗↓The  layout of this example is due to R. Davis.← 
.P104:

.BEGIN TURN ON "\";NOFILL;TABS 5,11,22,31,37,49,55,61,72,74;preface 0 mills;
.<<BEGIN TURN ON "\";NOFILL;TABS 5,11,22,28,34,46,52,58,69,71;preface 0 mills;>>
.KRK
.TURN OFF "←";
\\\\\\\\\%B⊃%*
\\\\\\\\\%Bεα→ %36%*
\\%3fact[3]\\\[x=0→ ...]\\*[x;fact[x-1]]\%bε←⊃%*
\\%1E%40%*\\\E%41%*\\\E%41%*\%b~ ~%*
\  \| /\\      \|  E%40%*\\      \|  E%40%*\%b$ ↑%*
\_______\=>\_______\=>\_______ =>\\\%32%*
\%3fact\| λ[[x][x=0→1;...]\ x\| 3\\ x\| 3\\\%b↑%*
\\\\\\\\\%B⊃ ~%*
\\\\\\\\\%Bε→$%*
\\%3fact[2]\\\[x=0→ ...]\\*[x;fact[x-1]]\%b~%*
\\%1E%41%*\\\E%42%*\\\E%42%*\%bε←⊃%*
\  \| E%40%*\\      \|  E%41%*\\      \|  E%41%*\%b$ ↑%*
=>\_______\=>\_______\=>\_______ =>\\\%31%*
\%3  x \| 3\\ x\| 2\\ x\| 2\\\%b↑%*
\\\\\\\\\\\%B~%*
\\\\\\\\\%B⊃ ~%*
\\\\\\\\\%Bε→$%*
\\%3fact[1]\\\[x=0→ ...]\\*[x;fact[x-1]]\%b~%*
\\%1E%42%*\\\E%43%*\\\E%43%*\%bε←⊃%*
\  \| E%41%*\\      \|  E%42%*\\      \|  E%42%*\%b$ ~%*
=>\_______\=>\_______\=>\_______ =>\\\%b~%*
\%3  x \| 2\\ x\| 1\\ x\| 1\\\%b↑%*
\\\\\\\\\\\%31%*
\\\\\\\\\\\%B↑%*
\\\\\\\\\\\%B~%*
\\%3fact[0]\\\[x=0→1; ...]\\\\%b⊃ ~%*
\\E%43%*\\\E%44%*\\\\%b~ ↑%*
\  \| E%42%*\\      \|  E%43%*\\  \%1send%*\%b~ ~%*
=>\_______\=>\_______\=> 1\\ %31 \%bε→$%*
\%3  x \| 1\\ x\| 0\\ \%1back up\%b$%*
.BOXB
.END
.APART
.FP
At the end of the first line we are faced with the evaluation of
%3*[x;fact[x-1]]%*. This requires the evaluation of the arguments
to *; this is done by %3evlis%*. First %3x%1 is evaluated and saved,⊗↓%1This
saved information is not explicitly represented in these pictures
or in  the Weizenbaum diagrams.←  then
the evaluation of %3fact[x-1]%* is begun
using  environment E%41%*. In E%41%*, %3x-1%*  gives %32%*  and
we find the definition of %3fact%* in E%40%*. In the second line
we set up E%42%* and evaluate %3fact[2]%*. Analogous situations
occur until the fourth line; at this time we suddenly find ourselves in
E%44%* with %3x%* bound to %30%*. The expression %3x=0%* is satisfied and
we start back up the right margin to conclude the nested evaluations 
of %3*[x;fact[x-1]]%*. This process finally terminates at the
top, returning  a value %36%*.
Notice   that we will get the correct binding of %3x%* locally.
It is important to note that the occurrence of %3fact%* within the body of
the definition of %3fact%* is %6global%*.⊗↓Notice that
%3eq%1, +, and * are also global.← We find the correct binding
for %3fact%* by searching the access chain.
We must search the access chain even though %3fact%1 is global.
We cannot shortcut the search by simply looking in E%40%1. A variable
might have been rebound in an enclosing environment and it would be
that binding we should discover.

.GROUP

As a final example showing access to   non-local variable bindings consider 
%3f[3]%* where  %3f#<=#λ[[x]#g[2]]%* and %3g#<=#λ[[y]#x+y]%*.

.BEGIN TURN ON "\";NOFILL;TABS 12,15,20,38,40,56,61,64,69,72,85;
.<<BEGIN TURN ON "\";NOFILL;TABS 17,20,25,38,40,56,61,64,69,72,85;>>
.KRK
.GROUP
.BOXA
\\%3f[3]\\\g[2]\\\x + y    
\\E%40%*\\\E%41%*\\\E%42%*    
\\| /\\   \| E%40%*\\\| E%41%*
\______\     =>\______\=>\______\          
\  %3f\| λ[[x] g[2]]\%3x\| 3\  \y\| 2       
\  %3g\| λ[[y] x+y]
.END
.BOXB
.FP
Notice that when we  evaluate %3x + y%* we find %3y%* has a local
value, but we must look down the access chain to find a binding for %3x%*.
.APART
.GROUP;
The scheme for using Weizenbaum environments for the current LISP subset
is:
.BEGIN INDENT 5,5,5;GROUP;
.P189:
When preparing a λ-binding, set up a new E%4new%* with
the λ-variables  as the local variable entries and add the values of the
arguments as the corresponding value entries.
The access slot of the new E%4new%* points
to the previous access environment.  The evaluation of the body of the
λ-expression takes place using the new table; when a local variable
is accessed we find it in E%4new%*; when a non-local  variable occurs, we
chase the access chain to find its value.
.pt2
When the evaluation of the body is completed, E%4new%* disappears
and the  previous environment is restored.
.END
.APART

You should verify that the current  access- and binding-scheme
espoused by LISP is faithfully described in these diagrams.




.CENT(Problem)
.P223:
.NL
1.##Environments really are a class of abstract
data structures: they include constructors, selectors, and recognizers.
To help discover what a set of such functions might be,
give a representation for Weizenbaum environments and  write  new versions
of  the symbol table  manipulating functions,
%3lookup%1 and %3mkenv%1, which will operate on Weizenbaum environments.
See {yon(P212)}.
.END "ENVS"
.SS(%3label%*,%3label%*,P38:)
.begin "label"
.FP
.BEGIN TURN ON "←";
Placing "λ" and a list of λ-variables in front
of an expresson designates the   variables which appear in
the λ-list as local variables. All other  variables
appearing in the expression are non-local.
For example, %3f%* is non-local in the following:
.BOXA
←%3f <= λ[[x][zerop[x] → 1; %et%* → *[x;f[x-1]]] ] %1
.BOXB
.FP
Clearly our intention is that the %3f%* appearing to the right of "<="
is the same as the %3f%* appearing to the left of "<=". 

.GROUP;
This has not been a problem for us.  We have simply pre-loaded the
symbol table, binding %3f%* to its definition; see {yon(P42)}. LISP
has  a  more elegant device for this binding. It is 
called the %3label%* operator and is written:
.BOXA
←%3label[%1<identifier>;<function>]  
.BOXB
.FP
Its evaluation
has  the effect of binding the <identifier> to the <function>.
The value constructed by executing  a %3label%*-expression is 
a representation of a function with name <identifier> and body <function>.
.APART
For example, a proper definition of %3fact%* is:
.BOXA
←%3label[fact; λ[[x][eq[x;0] → 1; %et%* → *[x;fact[sub1[x]]]]]]%1
.BOXB
To include %3label%* in the LISP syntax add:

.BEGIN TABIT1(11);CENTERIT;
.BOXA
←<function>::= %3label%*[<identifier>;<function>]
.BOXB
.FP
and the S-expr translation of the %3label%* construct should naturally be:
.BOXA
←%eR%f( %3label[f;fn] %f)%3 = (LABEL %eR%f( %3f %f)%3  %eR%f( %3fn %f)%3)%1
.BOXB
.FP
Note that %3label%* is a special form, not a call-by-value function.
.END
Since the %3label%1 operator creates a function, it  
should appear in the function position  of a function application.
A typical application of the  %3label%* construct, say 
%3label[f;λ[[x] %9x%*[x]]][%7e%3]%1,
results in the following environmental picture when we get ready to evaluate
%9x%3[x]%1:

.BEGIN TURN ON "\";NOFILL;TABS  5,15,31,37,40,46,52;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS  5,13,28,33,36,51,56,59,64,67,70;GROUP;>>
.KRK
.BOXA
\%3label[f;λ[[x] %9x%*[x]]][%7e%3]%1        \\%9x%3[%7e%3]%1
\\E%40%*\\\E%41%*
\ \ | /\\   \| E%40%*
\   ___________\=>     \______
\          \ |            \\%3f\| λ[[x] %9x%*[x]]
.BOXB
.END
.FP
Notice that %3label[f;λ[[x]%9x%3]][%7e%3]%1 is equivalent to
%3λ[[x]%9x%3[%7e%3]][quote[%7e%3]]%1;
notice too that the definition does not appear in the global table E%40%1.
We use %3label%1 to create temporary function definitions.
Such  definitions disappear 
when the environment in which the %3label%1 was executed is no longer
accessible to the computation.
Thus within the evaluation of the body %9x%3[x]%1
a  recursive call on %3f%*
will refer to the definition of %3f%1 located
in E%41%1 so long as %3f%1 is not rebound in %9x%1; 
once we have completed the computation
initialized in E%40%1 the definition of %3f%1 will disappear.
If %3f%*
is not recursive, then the use of %3label%*  is unnecessary; an
anonymous function application will suffice.
.BEGIN TURN ON "#";

What about statements like "evaluate %3g[A;B]%* where 
%3g#<=#λ[[x;y]#...#f[u;v]#...]%* and %3f#<=#λ[[x;y]#...#]%1#?"
%3label%* defines only one function; we may not say %3label[f,g;#...#]%*.
What we %6can%* do is  embed the %3label%*-definition for %3f%* within
the %3label%*-definition for %3g%*.⊗↓Indeed %6every%* occurrence of %3f%*
must be replaced by the %3label[f;...]%1 construct.←  Thus:

.BEGIN CENTER;SELECT 3;
.BOXA
label[g;#λ[[x;y]#...#label[f;#λ[[x;y]#...#]][u;v]#...]]%* 
.BOXB
.END
Several languages allow a simpler notation for giving
mutually recursive definitions; see ⊗↑[Rey#72]↑, ⊗↑[Hew#74]↑, or ⊗↑[Sus#75]↑.

It can be shown that the %3label%1 operator is superfluous; the same
effect can be  obtained by a complicated λ-binding.  However our point
here is not to be "minimal", but to be "useful".
Implementations of LISP offer other definitional facilities, with "<="
having the effect of permanently establishing the definition in E%40%1.
.END

The apparent simplicity of the %3label%* operator is partly due to
misconception and partly due to the restrictions placed on the current
subset of LISP. The following sections will illuminate
some of these difficulties.

.CENT(Problems);
.NL
1.##Show one way to change %3eval%* to handle %3label%*. 
.NL
2.##Express the definition of %3reverse%* given on {yon(P97)} using
%3label%*.
.BEGIN GROUP;
.NL
3.##Evaluate the following:

.SELECT 3;CENTERIT;
.boxa
←λ[[y] label[fn;fn%42%*][%ef%*]] [%ef%*]
.PT2
%1where:%3←fn%42%* <= λ[[x][y → 1; x → 2; %et%* → fn%41%*[%et%*]]
.PT2
%1and:%3←fn%41%* <= λ[[y] fn[y]]
.END
.END
.end "label"
.SS(Functional Arguments and Functional Values,functional argument,P76:)
.begin "funarg"
.BEGIN TURN ON "#","←";
.FP
Recall our discussion of :
.BEGIN CENTERIT;SELECT 3;
.BOXA
←%3eval[(F#2#3);((F#.#(LAMBDA (X#Y) (PLUS#(EXPT#X#2) Y))))]%*
.BOXB
.END
.FP
We now know this is equivalent to: 
.BEGIN CENTERIT;
.BOXA
←%3eval[((LABEL#F#(LAMBDA (X#Y) (PLUS#(EXPT#X#2)#Y)))#2#3);( )]%1 
.BOXB
.END
.FP
In either case, the effect is to bind the name %3f%* to the λ-expression.
Binding  also occurs when %3f%* is called: we bind %3x%* to %32%*, and %3y%*
to %33%*.
In the latter case we are binding simple values; in the former we are binding
functions as values. We have decided that the necessary ingredients to
characterize a functional value⊗↓It would be better
to call these constructs "procedure  values" since we will
take a decidedly algorithmic interpretation of them.← 
are a representation of the formal parameters, and a representation of the 
expression described in the body of the function.
In this section we will examine the adequacy of that decision.
We begin informally with a few examples.

Assume we have a list %3l%* of dotted-pairs %9α%41%1#,...,#%9α%4n%1, and we
wish to form a new list  of the form %3(car[%9α%41%3]#...#%3car[%9α%4n%3])%1.
That is we wish to apply %3car%* to each of the elements of %3l%*. Such a function is 
easy to write: 
.BOXA
←%3carfirst <= λ[[l][null[l] → ( ); %et%* → concat[car[first[l]];carfirst[rest[l]]]]]%1
.BOXB

Now suppose we wish to write a more general function, which instead 
of being specific to %3car%*, will take an %6arbitrary%* unary function %3f%* and
apply it to each of the elements of %3l%*, 
generating %3(f[%9α%41%3],#...,#%3f[%9α%4n%3])%1.
Such a function could plausibly be defined as follows:

.P34:
.BOXA
.BEGIN tabit2(5,27);
\%3mapfirst <= λ[[fn;l][\null[l] → ( ); 
\\%et%* → concat[fn[first[l]];mapfirst[fn;rest[l]]]]] %1
.END
.BOXB
.FP
Thus the first calculation we requested above could be expressed as:
.BOXA
←%3mapfirst[car;l]%1   .......###or could it?
.BOXB
.FP
Recalling LISP's penchant for call-by-value evaluation, we might believe
that the computation would not be done as expected. We do %6not%* want the
argument %3car%* evaluated
to produce an S-expr value; rather, we want its evaluation
to produce a representation of a primitive function, suitable for
application.  There are two ways out of this dilemma. One solution is to
suppress the evaluation of %3car%1, postponing it until the %3apply%1 function
can recognize that a function name has  been seen.
We have seen  one artifact in LISP
to subdue evaluation: we can make it a constant by %3quote%1-ing it. Indeed,
%3mapfirst[quote[car];l] %1or  %3mapfirst[CAR;l]%1 will work.
You should convince yourself that %3mapfirst[CAR;l]%1 will compute %3carfirst[l]%*;
that exercise requires examining the details of %3eval%1.

A second solution exists and is the one we will pursue. We 
say that the "value" of %3car%1 %6is%1 the description of the program which
computes  %3car%1. Since %3car%1 is a primitive,
that description is machine code for this specific implementation.


Before going on to more complex examples it would be well to note that
%3mapfirst%* is a different kind of LISP function from those we have seen before.
The first argument to %3mapfirst%* is expected to  represent
 a function. Notice
that the argument %3fn%* appears in the body of %3mapfirst%* in a position reserved
for functions. Therefore any  parameter bound to %3fn%* is expected to be a 
function. 
Such a  use  of a function is called a %2functional argument%*.

The first trick we used above, representing the functional argument %3car%1 as a 
constant %3CAR%1,
can be applied to other instances of functional arguments. 

Thus the functional argument:
.BOXA
←%3λ[[x] f[g[x]]%* 
.PT2;pt2;pt2
.fp
could be represented as,########%3(LAMBDA (X) (F (G X))) %*
.BOXB
.FP
The trick is  called %3QUOTE%*-ing
the functional argument since the S-expr representation of an
instance of such a construct is a %3QUOTE%1-ed expression.  
%3QUOTE%1-ing is not strictly necessary if we follow the second alternative above
and use the evaluator described in {yonss(P6)}. Worse yet, %3QUOTE%1-ing
is also not sufficient to capture the intended meaning in all cases of functional
parameters. 
To understand why %3QUOTE%1-ing is not sufficient we need 
a slightly more complex set of examples.  First we try:
.boxa
←%3mapfirst[ λ[[x] concat[x;( )]];(A B C D)]%1####⊗↓Note that we
do not use %3quote%1. Some implementations do not support this notation.
Some require %3quote%1, and still others give a different interpretation to 
unembellished functions appearing as actual parameters.← 
.boxb
.FP
which we expect to evaluate to %3((A)#(B)#(C)#(D))%*
.BEGIN TURN ON "\";NOFILL;TABS  7,16,32,42,45,61,65,69;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS  5,13,28,37,40,56,60,63,68,71,74;GROUP;>>
.BOXA
.KRK
 %3mapfirst[ λ[[x] concat[x;( )]]; ... ]\\[null[l] ... ]%1
\\E%40%*\\\E%41%*
\ \| /\\ \| E%40%*
\______________\=>\__________\=>  . . .
 %3    mapfirst\| λ[[fn;l][null[l] ... ]]\l\| (A  B  C D)
\\\\fn\| λ[[x] concat[x;( )]]%1
.BOXB
.END
.BEGIN TURN ON "\";NOFILL;TABS  25,33,48,53,56,61,76,79;GROUP;
.KRK
Since %3null[l]%* is false, the problem reduces to:

\%3concat[fn[first[l]];mapfirst[fn;rest[l]]].%1
\\E%41%*
\ \| E%40%*
\______________
\     %3l\| (A  B  C D)
\     fn\| λ[[x] concat[x;( )]]%1
.BOXB
.END
.FP
Since  we are using
 call-by-value we have to evaluate the arguments
to %3concat%*; that requires evaluating %3fn[first[l]]%*. The value of
%3l%* we find locally and evaluate %3first[l]%*, getting %3A%*. The value
for %3fn%* is also found locally, and since it is  the representation of
a λ-definition, we set up a
new environment in which to evaluate the body of %3fn%*, binding the λ-variable
%3x%* to %3A%*:

.BEGIN TURN ON "\";NOFILL;TABS  25,33,48,53,56,71,76;GROUP;
.KRK
.BOXA
\     %3concat[x;( )]%1
\\E%42%*
\ \| E%41%*
\______________
\      %3x\|  A%1
.BOXB
.END
.FP
The expected evaluation takes place: %3(A)%* is computed and returned to
environment E%41%1  so that we may continue the evaluation %3mapfirst[fn;rest[l]]%*.

However, consider the following variant of this last  example.
Define:
.BOXA
←%3foo <= λ[[l] mapfirst[ λ[[x]concat[x;l]]; (A B C D)]%*  
.BOXB
.FP
It would
seem that %3foo[(#)]%* should also give %3((A)#(B)#(C)#(D))%*
since %3l%* will be bound to %3(#)%* and therefore the %3l%* in the functional
argument will effectively be %3(#)%*.

.BEGIN TURN ON "\";NOFILL;TABS    1,11,27,33,37,48,54,58,64,67,70;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS  1, 9,24,29,32,42,47,50,55,58,61;GROUP;>>
.KRK
.BOXA
\     %3foo[( )]######mapfirst[ λ[[x] concat[x;l]];...]\\[null[l] ...  ]
\\%1E%40%*\\\E%41%*\\\E%42%*     
\ \ | /\\ \| E%40%*\\   \| E%41%*    
\______________\=>\______\=>\______     =>  ...
\     %3foo\| λ[[l]... ]  \\l\| ( )         \\l\| (A  B  C D)
\mapfirst\| λ[[fn;l][null[l]...]]\\\  \fn\| λ[[x] concat[x;l]]%*
.BOXB
.END
.FP
%3null[l]%* is false since %3l%* is %3(A B C D)%*, so we evaluate
%3concat[fn[first[l]]#...#]%*. This involves evaluating %3first[l]%* 
in E%42%1, giving %3A%*. We evaluate  %3fn%* in E%42%1 and,
finding a representation of a  λ-definition, 
we make  a new environment E%43%1 in which to evaluate
the body of %3fn%*. 
.GROUP;
As we make E%43%1, we add an entry binding %3x%* to %3A%*
and we  settle down in E%43%1 to evaluate %3concat[x;l]%*:

.BEGIN TABIT2(25,30);GROUP;
.BOXA
\     %3concat[x;l]%1
\\E%43%*
\      \| E%42%*
\__________
\ %3  x\| A
.BOXB
.END
.APART;
.FP
Since %3l%* is non-local to E%43%1, we follow the access chain to find its value
in E%42%1 to be %3(A B C D)%1. But that's not the expected value! We expected
to find %3(#)%*, which was hidden away in E%41%1. 

The trouble here is that
%3l%* was rebound in the interim. The first thing to note is that the problem
is caused by free variables and dynamic binding: %3l%* is free in the functional argument.
Local variables aren't problematic; neither are global variables.
The desired binding for %3l%* is the one which was current
when we were binding the functional argument to the formal parameter %3fn%*.
A plausible solution then is to replace all non-local variables with their values
at the time we recognize the functional argument. This will not always suffice.
See {yon(P94)} for a counterexample.
A more promising solution 
associates the name of the current environment with the function and use 
that pair as the value to be given to the formal parameter. 
When we want to apply the functional argument we set up a new environment,
  introducing a local table with the λ-variables bound to their values;
only %6now%* we use the saved environment as the beginning of the access chain.
The values of
any non-local variables which we encounter in the process of applying the functional
argument will be searched for in the saved environment. 

To initialize this process we must be able to recognize 
the occurrence of a functional
argument.  To that end, we introduce a new operator called ⊗→%3function%*↔←. 
This operator takes one argument: a representation of the function. The effect of 
%3function%1 will be to construct a value representing that argument and the
environment which was current when the %3function%1-instance was evaluated.

In the current example, we would recognize the %3function%*-construct while 
evaluating the arguments to %3mapfirst%*; the environment which was current 
then was E%41%*. Therefore as we build E%42%* we want to associate the pair
%3λ[[x]#concat[x;l]]#-#%1E%41%* with the formal parameter %3fn%*. Whenever
we apply %3fn%* we want to use %3λ[[x]#concat[x;l]]%*; and within that
context, whenever we want %3l%*, we want the value of %3l%* in E%41%*.

The  function-environment pair is called a %2⊗→closure↔←%* or
%2⊗→funarg↔←%*.
In our diagrams we will designate the pair as:
.BOXA
←<function>:<environment>.
.BOXB
.FP
Therefore, in our example we should designate the value of the functional argument
as:
.BOXA
←%3λ[[x] concat[x;l]]%1:E%41%1 
.BOXB
.FP
We must also extend the manipulation of Weizenbaum environments to 
handle such constructions.
The process which recognizes λ-definitions and sets up new environments must now
watch for funargs. 
When it sees one it uses the associated
environment as the access environment.
Let's do the example again.

.BEGIN TURN ON "\";NOFILL;TABS  5,13,31,36,39,51,56,59,64,67,70;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS  5,13,28,33,36,51,56,59,64,67,70;GROUP;>>
.KRK
.BOXA
\  %3foo[( )]###mapfirst[function[λ[[x] concat[x;l]]; ..]##[null[l] ... ]
\\E%40%*\\\E%41%*\\\E%42%*     
\ \| /\\\| E%40%*\\\| E%41%*    
\______________\=>\______\=>\______     => . . .
\     %3foo\| λ[[l]...    \\l\| ( )         \\l\| (A  B  C D)
 mapfirst\| λ[[fn;l][null[l]...]]\\\\fn\| λ[[x] concat[x;l]]%1:E%41%1
.BOXB
.END
.FP
Things are as before except now %3fn%1 is bound to the  funarg pair 
in E%42%*.
We look up %3fn%* in E%42%1 and,
finding a λ-definition, we make  a new environment E%43%1 in which to evaluate
the body of %3fn%*. As we make E%43%1, we add an entry binding %3x%* to %3A%*.
But now since the λ-definition is a funarg we make the access environment  
E%41%1 as saved with %3fn%*.
Thus we settle down in E%43%1 to evaluate %3concat[x;l]%*:

.BEGIN TABIT2(25,30);GROUP;
.BOXA
\\%3concat[x;l]%1
\\E%43%*
\      \| E%41%*
\__________
\ %3  x\| A
.BOXB
.END
.FP
Since %3l%* is non-local to E%43%1, we follow the access chain to find its value
in E%41%1 to be %3(#)%1 as desired.
Thus instead of simply tracing back to the previous environment we detour
around E%42%*:

.BEGIN SELECT g;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#";
.TURN ON "∞" FOR "%";
.TURN ON "?" FOR "\";
.TURN OFF "\","←";
.TABS 30,33;
.KRK
.BOXA
?∞1E∞40∞g
?↑
?~
?∞1E∞41∞g←?⊃			    
?↑?.
?~?.
?∞1E∞42∞g?↑			    
?↑?.
?~?.
?∞1E∞43∞g→?$			    
.BOXB
.END
.FP
However, there is still some information which we must make explicit
if these Weizenbaum diagrams are to faithfully represent the process of evaluation.
Namely, after we have finished the evaluation of %3concat[x;l]%1 we are to
restore a previous environment. Which one is it?  It isn't E%41%*,
it's E%42%1! That information is not available in our diagram, so
we must correct the situation.

In the left-hand quadrant of our diagram we
place the name of the environment which we wish restored when we leave the
current environment. 
That environment name will be called the %2⊗→control environment↔←%*,
and will head a chain of environments, called the control chain.⊗↓In Algol, 
the access chain is called the static chain, and the control
chain is called the dynamic chain.← 
Here's the correct picture:

.BEGIN TABIT2(25,30);GROUP;
.P190:
.BOXA
\\%3concat[x;l]%1
\\E%43%*
\E%42%*\| E%41%*
\__________
\ %3  x\| A
.BOXB
.END
.FP
So after we have finished the computation in E%43%* we return control to E%42%*.
Thus the general structure of an environment is as follows:

.BEGIN TABIT2(33,42);GROUP;
.BOXA
\\%2Form%1
\\E%4current%*
\E%4control%1\| E%4access%*
\_________________________
\var\| value
\%3x%41%1\| . . .
\%3x%42%1\| . . .
\. . .\| . . .
\%3x%4n%1\| . . .
\\|
.BOXB
.END
Consider 
 another example, involving a function to produce the composition 
of two unary functions. We will call the function %3compose%*. The value 
returned by %3compose%* will be a function; that means  %3compose%* will produce a
functional value:
.BEGIN CENTERIT;SELECT 3;GROUP;
.BOXA
←compose[function[car];function[cdr]] = cadr
.pt2
%1with a plausible definition as:%3
.pt2
←compose <= λ[[f;g] λ[[x]f[g[x]]]]
.BOXB
.END
.FP
This definition of %3compose%* is almost right.  The
value returned by %3compose%* is to be a function. Indeed it is an instance of
a %2⊗→functional value↔←%*, so, as with functional arguments, it needs to be
decorated with %3function%* so that 
the evaluator will save the environment which contains the right
bindings for %3f%* and %3g%*. That environment is  the
one which was current when the %3function%*-construct was recognized.
So we write:
.BOXA
.p152:
.BEGIN CENTERIT
←%3compose <= λ[[f;g] function[λ[[x] f[g[x]]]]] 
.PT18
.FP
%1Now try:←%3app[cons[A;(B . C)];compose[function[car];function[cdr]]]%1
.FP
.PT2;pt2
%1where:%3←app <= λ[[y;f] f[y]]%1
.BOXB
.END
.FP
As usual we evaluate the arguments to %3app%*, bind the results
to %3y%* and %3f%* and evaluate the body of %3app%*. 

.BEGIN TURN ON "\";NOFILL;TABS 5,15,23,28,43;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS 5,13,28,33,36;GROUP;>>
.BOXA
.KRK
\%3app[cons[A;(B . C)];compose[function[car];function[cdr]]]%1
\\\%1E%40%*
\\ \/| /
\\______________
\\     %3app\ | λ[[y;f] f[y]]
\\compose\ | λ[[f;g] function[λ[[x] f[g[x]]]]]%1
.BOXB
.END
.FP
Evaluation of the first argument to %3app%* brings no surprises; we get
%3(A#.#(B#.#C))%1. We begin evaluating the second argument;
we find the definition of %3compose%* in the environment and
since it is a λ-definition we set up a new environment, E%41%*, and evaluate
the body %3function[λ[[x]#f[g[x]]]]%*:

.BEGIN TURN ON "\";NOFILL;TABS  25,33,48,53,56,71;GROUP;
.KRK
.BOXA
\%3function[λ[[x] f[g[x]]]]%*
\\%1E%41%*
\     E%40%*\| E%40%*
\     __________
\       %3f\| car%1:E%40%3
\       g\| cdr%1:E%40%1
.BOXB
.END
.FP
Again, the recognition of the %3function%*-construct says return a funarg-pair
as value. The environment we associate is the current one, E%41%*. We now go back
to E%40%*, using the control chain. Since both arguments to %3app%* are now
evaluated, we find the definition of %3app%* and set up a new environment E%42%*.
Thus:

.BEGIN TURN ON "\";NOFILL;TABS  15,23,38,43,46,61;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS  15,23,38,43,46,61;GROUP;>>
.KRK
.BOXA
\\%3f[y]\\\f[g[x]]%1
\\E%42%*\\\E%43%*
\   E%40%*\| E%40%*\\E%42%*\| E%41%*    
\    __________\=>\_________
\     %3y\| (A . (B . C))\\x\| (A . (B . C))
\     f\| λ[[x] f[g[x]]]%1:E%41%1
.BOXB
.END
.FP
The form to be evaluated in E%42%* is %3f[y]%*; we find %3y%* and %3f%*
both locally. We evaluate the argument %3y%1, 
then since %3f%* is a λ-definition, we set up a new environment
binding the λ-variable %3x%* to the value %3(A#.#(B#.#C))%*. But the λ-definition
is also a funarg; therefore the access environment stored in E%43%* is E%41%*.
The control component of E%43%* is set to the prior environment, E%42%*; and
we begin evaluation of the body %3f[g[x]]%*.

Now in E%43%* we find %3x%* locally but have to resort to the access chain to
find %3f%* and %3g%*; using funargs, we have set up the appropriate 
environments. From E%43%* we have access to E%41%*:⊗↓We can go from 
there to E%40%* if it were needed.← 

.BEGIN SELECT g;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","\","←";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
			    ∞1E∞40∞G
			    /\
			   /  \
			  /    \
			 ∞1E∞41∞G     ∞1E∞42∞g
			   ∞fK∞*     \
			      ∞fK∞*   \
				 ←-∞1E∞43∞g
.BOXB
.END
.FP
The rest of the evaluation goes without incident: we finish the evaluation
in E%43%* and return to E%42%* and finally to E%40%* following the control
evironments.


Notice that %3f%1 and %3g%* in the body of %3compose%* are free variables
and therefore their bindings are not to be found in the local environment.
Since the interesting applications of such functions usually involve
free variables, we must deal with them.
In particular, the  %3label%1 operator will typically involve free
variables. We remarked that %3f%1 in:
.BEGIN CENTERIT;
.BOXA
←%3f <= λ[[x][zerop[x] → 1; %et%* → *[x;f[x-1]]] ]%1
.BOXB
.END
.FP
is free. But we want the occurrence of %3f%1 on the right to be
synonymous with the %3f%1 being defined  on the left. We can do this
by "tying a knot" in the access environment chain. Therefore, we should modify the
diagram for %3label%1 to be:

.BEGIN TURN ON "\";NOFILL;TABS  5,13,28,33,36,51,56,59,64,67,70;GROUP;
.KRK
.P192:
.BOXA
\%3label[f;λ[[x] %9x%*[x]]][%7e%3]%1        \%9x%3[%7e%3]%1
\\E%40%*\\\E%41%*
\ \ | /\\\| E%40%*
\      ________\=> \______
\          \              \\%3f\| λ[[x] %9x%*[x]]%1:E%41%3
.BOXB
.END
.FP
Notice that the effect of %3label%1 is  to build %3function[λ[[x] %9x%3]]%1
and associate that with %3f%1.
If we attempted to implement %3function[%9f%3]%1 by replacing all non-local 
variables in %9f%1 by their current values we wouldn't always get what we expect.

.BEGIN CENTERIT;
.P94:
.krk
.pt2;pt2
Consider ←%3 fact <= λ[[x][x=0 → 1; %et%* → *[x;fact[x-1]]]]%1 
.pt2;pt2
.END


.BEGIN TABIT3(30,34,38);GROUP;TURN OFF "←";
If the current environment is E%4i%1:
.boxa
\\E%4i%*
\E%4c%*\|\E%4a%*
\___________
\%3fact%*\| %3foo%*
.BOXB
.APART
.GROUP
then executing %3<= %*  should give something like:
.BOXA
\\E%4i%*
\E%4c%*\|\E%4a%*
\___________
\%3fact%*\| %3λ[[x] ...fact[x-1]]%1 :E%4i%*
.APART
.GROUP
.BOXB
rather than:
\\E%4i%*
\E%4c%*\|\E%4a%*
\___________
\%3fact%*\| %3λ[[x] ...foo[x-1]] 
.END
.BOXB
Our final step is to include a 
data structure representation of the %3function%1 construct.
The translation scheme is simple:
represent %3function[%9x%3]%1 as %3(FUNCTION %eR%f(%9x%f)%3)%1.
.BEGIN CENTERIT;GROUP;KRK
.BOXA
Thus:←%3function[λ[[x] f[g[x]]] 
.PT2
%* has an %eR%*-image of######%3(FUNCTION (LAMBDA (X) (F (G X)))) %*
.BOXB
.END
.FP
We must  also develop new sections of %3eval%1 to deal with 
%3FUNCTION%1. The device LISP used to associate 
environments with functions is called
the ⊗→%3FUNARG%*↔← device.⊗↓More is said about implementations of %3FUNARG%* 
in {yonss(P3)}.← 
When %3eval%* sees  the construction %3(FUNCTION %1fn%3)%* it returns as value
the list:
.BOXA
←%3(FUNARG###%*fn### "saved"%3)%* 
.BOXB
.FP
where "saved" represents a pointer to the current symbol table.
This representation, as a list of three objects, is  called a  
%2funarg triple%1.
It is  %3apply%* that recognizes %3(FUNARG %*fn %1"saved"%3)%1.
When we are %6calling%3 fn%1, we use the "saved" symbol table
for accessing non-local  variables.  

.P215:
Thus there are %6two%* environments involved in the proper handling of functional
arguments. First there is the environment which is saved with the %3FUNARG%*.
This is called the %2⊗→binding environment↔←%* since it is the 
environment  current at the time the functional argument was constructed
or bound. The second environment, called the %2⊗→activation environment↔←%*
or application environment,
is the environment which is current 
immediately before the functional argument is %6applied%*
or activated.

It is the duty of %3eval%* and %3apply%* to use the %3FUNARG%* device
to maintain the proper control of the activation and binding environments.
.<<pic of funarg execution>>
.P79:
.GROUP;
Finally, we should update our description of the  usage 
of Weizenbaum environments given on {YON(P189)}:
.BEGIN INDENT 5,5;
When the %3function%1 construct is recognized, we manufacture a %3FUNARG%1 triple
consisting of the atom %3FUNARG%1, the function described in the
instance of %3function%1, and the current environment.
This triple is the value of the %3function%1 construct and may  be bound
to any LISP variable; typically the LISP variable will appear in an expression
in a position reserved for functions.


When doing a λ-binding, set up a new E%4new%* with
the λ-variables  as the local variable entries and the values of the
arguments as the corresponding value entries.
The control slot of  E%4new%*  always points
to the previous symbol table. The access slot also points to the previous
environment unless the function being applied is a %3FUNARG%1.   
If it is a %3FUNARG%1, then set the access slot to the environment
which was saved with the %3FUNARG%1.

The evaluation of the body of the
λ-expression takes place using E%4new%1; when a local variable
is accessed we find it in E%4new%*; when a non-local  variable occurs, we
chase the access chain to find its value.
When the evaluation of the body is completed,
the  previous environment is restored.
 E%4new%* disappears unless it has been saved in a functional object constructed
during the evaluation of the body, and that object is returned as a
functional value.⊗↓In fact, LISP will allow the retention of environments
in more general ways since funarg triples can be manipulated
as data structures.←
.END
.APART

.P279:
Notice that there is a certain asymmetry about access and control.
The control slot always points at the previous environment, while the access
slot may vary. It may follow control, as is the case on simple function calls;
it may point to an environment earlier in   the control chain, as is the case for
functional arguments; it may point to an environment which control cannot
return to, as is the case for functional values; or it may point to itself
as is the case for %3label%1's revised implementation.

There is another asymmetry in the properties of access and control.
The access environment is a self-sufficient data structure; it can be described
and manipulated as such using the usual constructors, selectors, and recognizers.
Typically such environments come into existence as a part of a computation; they
are constructed during the λ-binding process.
We can implicitly
save such an environment through the %3FUNARG%1 device; and
we can explicitly build
such environments using the data structure operations and pass them to %3eval%1  
as a symbol table. But symbol tables are independent of the method used to create 
them. In particular, once a table has been captured by a %3FUNARG%1 we need
not retain any information about the computation which  created that table.
However the idea of "control" and "state of computation" is integrally tied
to access structure.
The state of the computation involves the expression currently being evaluated,
the history of those computations which are suspended and waiting for the
completion of the current computation, and it also involves the access environment
since that is necessary for the correct evaluation of variables.
To "save the state of computation" implies saving
the partial computation to that point, saving the expression being evaluated, and
saving the current access environment. 

To a large extent, "control environment" is a misnomer. What we are intending
to capture is the idea of a suspended computation: suspended until the
subsidiary computation has been completed. Part of the suspended computation
%6is%1 the "control environment", but there's more. The Weizenbaum diagrams
show part of the information; they show the environments and the expressions
being evaluated. However they leave implicit the dynamics of the computation:
which argument is being evaluated, and where  the partial results  are being
stored, and where in the expression  we are to continue  when the subsidiary
computation is completed. In {yonss(P187)} we will develop  a different
%3eval%1 family which will make much of this information explicit.
Also in {yonss(P187)} we will examine the possibility of expanding 
the behavior of control
slots. That is, allowing environments other than the predecessor to appear in the
control slot of an environment.



We have already remarked that functions are
parametric values; to that we must add that functions may also 
be tied to the environment
in which they were created; they cannot be  evaluated %3in vacuo%*.
.P89:
What does this say about "<="? It %6still%* appears to act like an assignment statement.
It is taking on more distinct character since it must associate environments with
the function body as it does the assignment.

The  implementation of  %3function%1
seems like a lot of work to allow a moderately obscure construct to appear in a language.
However constructs like functional arguments appear in several programming languages
under different guises. Usually the syntax of the language is sufficiently
complex that the true behavior  and implications of
devices  like functional arguments is misunderstood. Faulty implementations
usually result. In LISP the problem and the solution   appear
with exceptional clarity.⊗↓LISP was the first 
programming language which allowed functional values.← 

.GROUP;
Here is a sketch of the abstract structure of the current %3eval%*.
.BOXA
.BEGIN SELECT 3;GROUP;TABIT2(12,41);
.P207:
eval <= λ[[exp;environ]
\[isvar[exp] → lookup[exp;environ];
\ isconst[exp] → denote[exp];
\ iscond[exp] → evcond[args%4c%3[exp];environ];
\ isfun[exp] → mkfunarg[exp;environ];
\ isfunc+args[exp] → apply[\func[exp];
\\evlis[arglist[exp];environ];
\\environ]] ]
.END
.APART
.BOXA
.GROUP
.BEGIN SELECT 3;GROUP;TABIT3(14,36,38);
%1where:%*
apply <= λ[[fn;args;environ]
\[isfunname[fn] →  ...;
\ islambda[fn] → eval[\body[fn];
\\mkenv[vars[fn];args;environ]];
\ isfunarg[fn] → apply[\func%41%*[fn];
\\\args;
\\\evn[fn]];
\       ...            ... ]]
.BOXB
.APART
.END
.FP
The reader is encouraged to complete the definitions, supplying appropriate
constructors, selectors and recognizers.


Now for some specific examples.
Most implementations  of LISP include a very useful class 
of ⊗→mapping functions↔←.

.DEF
⊗→%3maplist%*↔← is a function of two arguments: 
%3fn%1, a unary function; and %3l%1, a list.
%3maplist%* applies the function %3fn%* 
to the list %3l%* and its tails (%3rest[l], rest[rest[l]],#..%1)
until %3l%* is reduced to %3(#)%*.
The value of %3maplist%* is the list of the values returned by %3fn%*.
Here's a definition of %3maplist%*:
.BOXB
.GROUP;
.begin CENTER
%3maplist <= λ[[fn;l][null[l] → ( ); %et%* → concat[fn[l];maplist[fn;rest[l]]]]]%1 
.end
.BOXA
.FP
Thus:
.BEGIN CENTER
%3maplist[function[reverse];(A B C D)] = ((D C B A) (D C B) (D C) (D))%* 
.END
.fp
%1The 
use of %3function%1 is not strictly necessary 
since %3reverse%1 does not reference free variables. 

.APART;
The  mapping functionals can  be generalized. For example (⊗↑[Moo#74]↑)
an application %3mapfirst[fn;l%41%3;#...;#l%4n%3]%1 would expect %3fn%1
to be an n-ary function to be applied to consecutive members of each %3l%4i%1,
building a list of the results of each application.


An interesting and non-trivial use of functional arguments
is shown on {yon(P136)} where we define a new control structure
suitable for describing algorithms built to operate on lists.
.CENT(Problems)
.NL
1.##What changes should be made to the LISP syntax equations to
allow functional arguments?
.NL
.P151:
2.##Use %3app%* on {yon(P152)} to define a function which computes factorial without
using %3label%* or explicit calls on the evaluator.
.NL
3.##Extend %3eval%* and friends to handle functional arguments.

.GROUP;
.P99:
.NL
4.##An interesting use of functional arguments involves ⊗→self-applicative functions↔←.
An application of a function %3f%* in a context %3f[...;f;...]%* is an instance
of self application.⊗↓Provided the designated argument position is a functional
argument.←  Self-applicative functions can be used to define recursive 
functions in such a way that the definition is not %6statically%* self-referential,
but is %6dynamically%* re-entrant.
For example, here is our canonical example, written using a self-applicative function:
.APART

.BEGIN CENTER;SELECT 3;GROUP;
.boxb
fact <= λ[[n] f[function[f]; n]]
.pt2;pt2
f <= λ[[g;n][n=0 → 1; %et%* → *[n; g[g; n-1]] ]]
.boxb
.END
.ONCE INDENT 4,4
Use Weizenbaum's environments to show the execution of %3fact[2]%*.
.END
.NL
5.##Write a LISP function to find the permutations on a set of %3n%1 elements.
For example %3perm[(A B C)]%1 gives 
.BEGIN CENTER ;
.boxa
%3((A B C) (A C B) (B C A) (B A C) (C A B) (C B A))%1
.END
.NL
6.##Write a generalized form of the %3diff%1 algorithm ({yonss(P41)})
to handle n-ary sums and products.
.end "funarg"
.SS(Binding Strategies and Implementations,binding strategy,P134:)
.begin "bind"
After the discussion of variables  in {yonss(P135)} and the
intervening discussions of environments, it should now be clear
that the root of the binding problem is free variables. 
We don't want to restrict the use of free variables too precipitously since they
are a very useful programming technique. For example, the possible alternative
of passing all global information through as extra parameters in calling
sequences is overly expensive;⊗↓Though much of that expense can be mitigated
by a clever compiler.←  often the most natural formulation of a problem
involves free variables.

Handling of free variables varies from programming language to programming
language.  The solution advocated by Algol-like languages is called %2⊗→static
binding↔←%* 
or %2⊗→lexical binding↔←%1 and dictates 
that all non-local references be fixed in the binding 
environment; thus free variables aren't really free in the sense that
we have a choice to make.
LISP at least gives you a choice.⊗↓However ⊗↑[Ste#76b]↑ shows that
dynamic binding can be simulated in a statically bound
LISP-like language.←  Using %3quote%* you will get
the dynamic binding on free variables in a functional argument; using
%3function%* gives the static interpretation.⊗↓A case can be made for even more
flexibility in the interpretation of free variables. We could ask that
the binding be done on a per variable basis.
That is we could declare which free variables are to be captured
statically and which are to be captured dynamically.  
We could also ask that %6both%1
bindings be available and supply  selectors which would access either the
dynamic or the static binding.←
There are no questions about Algol's interpretation of functional values:
the construct is not allowed. When we discuss implementation of binding
strategies in {yonsec(P188)}
we will see why.

The binding strategy determines %6when%1 the variables will receive values; the
implementation determines %6how%1 those bindings are to be accomplished and
therefore, how the lookup of values is to be accomplished.
We have seen one implementation in the %3assoc#-#pairlis%1 pair 
({yonss(P6)},#{yon(P213)}),
and on {yon(P223)} suggested a related implementation using  Weizenbaum
environments. Now we examine another implementation.


The most general environment structure which LISP creates is a tree
of local symbol tables, rooted in the global table. The typical LISP
computation generates a single branch, but functional arguments and values
can generate additional branches. Locating a variable %3n%1 involved
searching the current branch from tip to root, looking for the first occurrence
of %3n%1. If %3n%1 was bound very deep, the search could be long.
Indeed the time is proportional to the depth of the branch; recall
our sample evaluation of %3equal%1 on {yon(P43)}. It has
been noted ⊗↑[Wegb#75]↑ that variables tend to be rebound rather seldom;
there are few occurrences  of any given variable on any particular branch.
If this is the case, then the search will examine many environment blocks
which do not contain the desired variable. If the number of bindings of
any variable is small compared to the number of environment blocks
which have to be searched to find those bindings, then we would like a viable
alternative to the %3assoc#-#pairlis%1 implementation of %3lookup#-#mkenv%1.
That is, a scheme whose search is proportional to the number of
bindings for a variable, rather than proportional to the depth of the
tree.
There is such an alternative.

.P217:
Namely, we  associate %6all%1 the values  possessed by %3n%1 with %3n%1 itself.
To signify which environment created the binding, we 
associate pairs consisting of the value and the environment name.
Thus the new
%3mkenv[vars;vals;env]%1 application must name a new 
environment, call it %3new%1, and
attach it to the tip of the
current branch in the environment tree. Also,
for each entry in %3vals%1, %3mkenv%1 must 
associate a value-%3new%1 pair with each name in %3vars%1.

 The %3lookup%1 procedure
is given the name %3n%1 and a branch in the environment tree. 
Assume that the tip node of the tree is named Env.
If %3n%1 has an attached value pair whose environment component is Env,
then the associated value is returned by %3lookup%1. Otherwise
the environment branch is searched recursively  by %3lookup%1 
 for the first  node in that branch which has an associated value
attached to %3n%1.
.BEGIN "foo" GROUP;
Here's a graphical description of this reorganized symbol table:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK

    E1              E2		   E4
⊂αααπααα⊃ 	⊂αααπααα⊃      ⊂αααπααα⊃
~ x ~ 3 ~       ~ y ~ 4 ~      ~ x ~ C ~
εαααβαααλ	%αααβααα$      %αααβααα$
~ y ~ 1 ~           ~		   ↓
εαααβαααλ  	    ↓	           E3
~ z ~ A ~           ~	       ⊂αααπααα⊃
%αααβααα$           ~          ~ z ~ 4 ~
    ~               ~          %αααβααα$
    ↓               ↓              ↓
    ~		    E0		   ~
    %ααααα→αααα→⊂αααπααα⊃←αααα←αααα$
                ~ y ~ 2 ~
	        εαααβαααλ
	        ~ z ~ 1 ~
	        %ααα∀ααα$

.begin turn on "%";
.le(6,The %3assoc-pairlis%* structure)
.end
.boxb
    		   x		  y		z
E1	E4    ⊂ααααπααα⊃     ⊂ααααπααα⊃    ⊂ααααπααα⊃
 ↓  E2	↓     ~ E1 ~ 3 ~     ~ E0 ~ 2 ~    ~ E0 ~ 1 ~
 \  ~  E3     εααααβαααλ     εααααβαααλ    εααααβαααλ
  \ ↓ /       ~ E4 ~ C ~     ~ E1 ~ 1 ~    ~ E1 ~ A ~
   \~/	      %αααα∀ααα$     εααααβαααλ    εααααβαααλ
    ↓ 			     ~ E2 ~ 4 ~    ~ E3 ~ 4 ~
    E0			     %αααα∀ααα$    %αααα∀ααα$
					   
.END

.begin turn on "%";
.le(6,The new  structures)
.end
.end "foo"
.APART
.boxb
.GROUP
.fp
Using the discussion of %3mkenv%1 on {yon(P212)}, we define:

.SELECT 3;
.BEGIN tabit1(10);
.P218:
.boxa
\alloc <=λ[[x] gensym[]]
.pt2
\link <= λ[[block;env] concat[block;env]]
.pt2
\send <= λ[[n;v;blk] addval[n;mkent[first[blk];v]]]
.boxb
.END

.BEGIN FILL;SELECT 1;
.fp
The function %3gensym%1 is to generate a new environment name  which 
 %3alloc%1 makes into a new tip node on the end of the current environment
branch. 

The function %3addval%1 adds a new entry to the variable %3n%1. The value of
%3addval%1 is %3env%1.
.END
.APART;
.GROUP;
.BEGIN SELECT 1;FILL;
The new %3lookup%1 is more complicated than the simple %3assoc%1. Given a node
in the environment branch, we must see if there is a related binding
for %3n%1. If there is, then that's the binding we want. If no binding is found
we look at the next deeper node on the tree, and check its bindings.
.END
.BEGIN tabit1(23);
.boxa
lookup <= λ[[n;env] λ[[z] look%9'%3[z;z;env]][getval[n]] ]
.pt2
look%9'%3 <= λ[[l;l1;env]\[null[l] →look%9'%3[l1;l1;rest[env]]
\ eq[name[first[l]];first[env]] → value[first[l]]
\ %et%3 → look%9'%3[rest[l];l1;env] ]]
.boxb
.END
.apart
This new scheme is called %2⊗→shallow binding↔←%1, and the %3assoc-pairlis%1
scheme is called %2⊗→deep binding↔←%1.
The essential differences between these two binding implementations is that
a deep binding search is keyed on the name of the variable, whereas a shallow
binding strategy is keyed on the environment name. These requirements
have corresponding implications for the
organization of the symbol tables.⊗↓The table organization discussed 
in this section
was also used in a language named LC%82%1 (⊗↑[Mit#70]↑). In their terminology,
"deep table"  was called  "scope oriented  organization" and "shallow table"
was called "name oriented organization".←

A further elaboration of the shallow scheme is possible. The essential aim 
of shallow binding is the reduction  of the search time for values of variables.
The current scheme  improves the situation, but if a variable is bound several
times we still may have to search the table of values associated with the atom.
The next modification arranges that
the correct binding is always found in a fixed location associated with the atom.
As with any scheme, the benefits are not without penalty; we will discuss some
of the tradeoffs after we describe the implementation.

With each variable %3n%1 we associate a %6single%1 entry called the %2⊗→value#cell↔←%1.
The binding and unbinding  mechanisms will maintain the correct value of the
variable  in the value cell. The scheme is a mixture of the two  previous
implementations.  
.GROUP;
The %3lookup%1 routine is similar to the shallow lookup:
.BEGIN SELECT 3;center
.boxa
%3lookup <= λ[[x;env] getval_cell[x]]
.END
.boxb
.fp
Notice that %3env%1 is ignored in %3lookup%1.
.APART;
.GROUP;

The binding routine is a bit more complex.
When binding %3n%1 we have to replace the current value cell with the new
binding.  We also have to  save the old binding so that it may be restored
when the  sub-computation is completed; this part of the implementation is 
like deep binding.   We perform most of the %3mkenv%1 operations
as given on {yon(p213)}, but require a new version of %3send%1. Instead of
placing the new bindings in the block built by %3send%1, we place the
current bindings there as we place the new bindings in the value cell.
The new definition of %3send%1 follows:
.BEGIN SELECT 3;center
.boxb
%3send <= λ[[var;val;block] concat[mkent[var;swp_val_cell[var;val]];block]]
.boxb
.END
.fp
where %3sw_val_cell%1 places %3val%1 in the value cell of %3var%1
and returns the old value.
.APART
.GROUP;
The unbinding operation is even  more complicated. When we leave an environment
we expect the prior environment to be  re-established. That is done
automatically by recursion in the deep implementation and
in the previous shallow binder. See {yon(P69)}; the recursive call
on %3eval%1 with the new  binding of %3environ%1  will lose its effect
as we leave %3eval%1. 

However,  the new scheme requires more; we must  restore the saved values
to the value cells, and recursion will not do that automatically.
We will discuss more of the details of this  process in {yonss(P134)} and
{yonss(P225)}, but the basic idea is to swap the contents of the
saved block back into the value cells as we  leave the inner call
on %3eval%1. Notice that we cannot simply throw away the old bindings
since a call on %3function%1 may have occurred. The %3funarg%1 triple can be
built as before: saving the current environment name (%6not%1 saving the current
contents of all the value cells).
The application of %3funarg%1s is  therefore more problematic. 
In the previous binding
implementations, all we needed to do was  establish the saved environment
name as the evironment to be used for non-local searches.  In this
latest binder, we must %6re-establish%1 the value cells which were
current when %3function%1 was recognized.  We will postpone this discussion
until {yonss(P225)} and {yonss(P228)}.
.APART

This latest implementation of binding is by far the most complex we have seen.
It gives fast access to values of variables, but requires more
effort in changing environments; that is particularly evident in the 
discussion of %3function%1#constructs.
We will discuss the relative merits of these implementations in more
detail in {yonsec(P188)}.
Be clear on the distinction between a binding strategy and a binding implementation.
The two strategies we have discussed are called "dynamic" and "static"; the
two implementations are called "deep" and "shallow". Either implementation
technique can be used with either binding strategy.


.CENT(Problems)
.NL
1.##Suggest an implementation of %3addval%1 which will improve the search efficiency
of %3lookup%1.

.P221:
.nl
2.##Analyze %3lookup%1 in a manner similar to that performed
on %3mkenv%1 on {yon(P212)}. Identify the parts of %3lookup%1 which are
independent of the binding implementation. Rewrite the shallow and deep
versions of %3lookup%1 in this more general setting.
.end "bind"
.SS(Special Forms and Macros,Special Form,P8:)
.fp
We have remarked that the evaluation scheme for LISP functions is
call-by-value and, for functions with multiple arguments, left-to-right
evaluation of arguments. We have also seen, in %3quote%* and %3cond%*,
that not all forms to be evaluated in LISP fall within this category.
The purpose of %3quote%* was to %6stop%* evaluation;
and the "argument list" to %3cond%* is also handled differently.
Since %3quote%1 and %3cond%1 were rather anomalous
we have called them %2special forms%*. Now
we would like to discuss special forms as a general technique.

Consider the predicates  ⊗→%3and%*↔← and ⊗→%3or%*↔←. We might wish to define
%3and%* to be a binary predicate such that %3and%* is true just in case
%6both%* arguments evaluate to %et%*, and define %3or%* to be binary
and false just in case both arguments evaluate to %ef%*.
Notice two points. First, there is really no reason to restrict these predicates
to be %6binary%*. Replacing the words "binary" by "n-ary" and "both" by "all"
in the above description has the desired effect.
Second, if we evaluate the arguments to these predicates in some order,
say left-to-right, then we could immediately determine that %3and%*
is false as soon as we come across an argument which  
evaluates to %ef%*; similarly a call on %3or%* for an arbitrary number
of arguments can be terminated as soon as we evaluate an argument giving
value %et%*.
But if we insist that %3and%* and %3or%* be LISP %6functions%* we can 
take advantage of neither of these observations. 
Rather we will
 define %3and%* and %3or%* as special forms and handle
the evaluation ourselves. Presently, the
only way to handle special forms is to make explicit modifications
to %3eval%*.⊗↓On {yon(P201)}  and in {yonss(P202)} we will discuss 
simple ways to add such forms without modifying %3eval%1.← 

.BEGIN CENTERIT;SELECT 3;GROUP;TABIT1(19);

%1Recognizers for the predicates must be added to %3eval%*:
.SELECT 3;
.BOXA
isand[e] → evand[arglist[e];environ];
.pt2
isor[e] → evor[arglist[e];environ];
.BOXB;KRK
%1where:%3

.P53:
evand <= λ[[l;a]\[null[l]→ %et%*;
\ eval[first[l];a] → evand[rest[l];a];
\ %et%* → %ef%*] ]
.end
.BEGIN CENTERIT;SELECT 3;GROUP;TABIT1(17);
.BOXA
evor <= λ[[l;a]\[null[l] → %ef%*;
\ eval[first[l];a] → %et%*;
\ %et%* → evor[rest[l];a]] ]
.BOXA
.END
.FP
Or, exploiting the duality of %3and%1 and %3or%1 (⊗↑[Ste#pc]↑):

.BEGIN SELECT 3;GROUP;TABIT1(23);
.BOXA
isand[e] → evandor[arglist[e];environ;%et%3];
.pt2
isor[e] → evandor[arglist[e];environ;%ef%3];
.PT2
evandor <= λ[[l;a;d]\[null[l] → d;
\ xor[d;eval[first[l];a]] → not[d];
\ %et%3 → evandor[rest[l];a;d]]]
.PT2
xor <= λ[[a;b][a → not[b]; %et%3 → b]]
.BOXB
.END
.FP
In either formulation there are
explicit calls on %3eval%*.⊗↓Also notice that the abstract versions of
%3evand%*, %3evor%1  and %3evandor%1 %6know%1 that the  
arguments are represented as a sequence and
the structure of the recursion implies a left-to-right evaluation.← 
This seems expensive, but the arguments must be evaluated.

.P18:
Special forms have been used for two purposes: one is to control the evaluation
of arguments; conditional expressions, quoted expressions,
%3and%1, and %3or%1 are examples. The second application  area is 
to create the effect of  call-by-value functions with an indefinite 
number of arguments  %6all%1 of which are to be 
evaluated; the LISP functions, %3list, append%1, and %3plus%1 are examples in this
category.

Even though we wish to define
these functions as if they had an arbitrary number of arguments, when
we  %6call%1  the function, the number of arguments to be
applied %6is%* known.⊗↓For example, at compile time
the number of arguments is known, and   
the compiler can often generate
 more efficient code than just calls on %3eval%*.←

.BEGIN GROUP;
Assume, for example, we wish to define %3plus%* as a function with
an indefinite number of arguments such that:

.BEGIN CENTERIT;SELECT 3;GROUP;
.boxa
←plus[4;5] = 9
.pt2
←plus[4;5;6] = 15
.pt2
←plus[4;add1[2];4] = 11
.boxb
.END
.END
.FP
We can  define %3plus%* in terms of a %6binary%*
addition function, %3*plus%*.

.BEGIN CENTERIT;SELECT 3;GROUP;
.boxa
←plus[4;5] = *plus[4;5] = 9
.pt2
←plus[4;5;6] = *plus[4;*plus[5;6]] = 15
.pt2
←plus[4;add1[2];4] = *plus[4;*plus[add1[2];4]] = 11
.boxb
.END
.FP
We %2expand%* calls on %3plus%* into a composition of calls on
%3*plus%*.
%3plus%* is being used as a %2macro%* and the expansion process in terms
of %3*plus%* is called %2macro expansion%*. The  macro expansion
generates a composition of calls on %3*plus%*.

A macro definition is a 
λ-expression of %6one%* argument. The call on a macro looks just like
an ordinary function call, but what is bound to the λ-variable is the whole
call on the macro.⊗↓A similar device, called "meta composition", is used in
⊗↑[Bac#73]↑.←
The task of the macro body is to
expand the macro call and return this expansion as its value.
This expanded form is passed back through %3eval%1 to complete the computation.
In {yonss(P202)} we will discuss the additional mechanisms which 
evaluators must possess for execution of macros.


.BEGIN TURN ON "#";
Let's define %3<%4m%*=%1 to mean "#is#defined#to#be#the#macro#...".
Then a simple macro definition of %3plus%* might be:
.END

.BEGIN SELECT 3;TABIT3(5,21,30);GROUP;
.BOXA
.P58:
\plus <%4m%*= λ[[l]\[eq[length[l];3] → concat[*PLUS;rest[l]];
\\ %et%* → list[\*PLUS;
\\\second[l];
\\\concat[PLUS;rest[rest[l]]]]]]
.BOXB
.END
.FP
Thus a call %3(PLUS 3 4 5)%* would bind %3l%* to %3(PLUS 3 4 5)%* and
the evaluation of the body would result in %3(*PLUS 3 (PLUS 4 5))%*.
Evaluation of this expression would result in another call on the macro.
This time %3l%* would be bound to %3(PLUS 4 5)%*. Now
%3eq[length[l];3]%* %2is%* true and the value returned is %3(*PLUS 4 5)%*.
This will be evaluated, giving %39%1; finally the outermost call on %3*PLUS%*
has all its arguments evaluated, and we get the final answer, %312%1.

A  more general macro expander can be described as:

.BEGIN SELECT 3;TABIT2(21,31);
.BOXA
expand <= λ[[fn;l]\[null[rest[l]] → l;
\ %et%3 → list[\fn; 
\\first[l]; 
\\expand[fn;rest[l]]]]]
.END
.BOXB
.FP
Then we can define %3plus%1 <%4m%3= %3λ[[l] expand[*PLUS;rest[l]]]%1.

In a similar manner, 
.boxa
%3append <%4m%3= λ[[l] expand[*APPEND;rest[l]]]%1 
.boxb
.fp
where %3*append%1 is the binary version of %3append%1.

Since the body
of a macro has available all of the evaluation mechanism of LISP, and
since the program structure of LISP is also the data structure, we can
perform arbitrary computations inside the expansion of the macro.

.P54:
The idea of macro processing is not recent.  Some of the earliest assemblers
had extensive macro facilities.  Lately macros have been used as a means
of extending so-called high level languages.
One of the most simple kinds of macros is %2textual substitution%*.
That is, when a use of a macro is detected we simply replace the call by its
body.  A slightly more sophisticated application is the %2syntax macro%*.
Everytime we come across an application of a syntax macro the expander 
processes it as if it had never been seen before even though much
of the expansion is repetitious. That is, syntax macros have no memory.

%2Computational macros%* are an attempt to reduce some of this repetition.
In this scheme a certain amount of processing is done at the time the macro
is %6defined%*. For example a computational subtree reflecting the body of the
macro might be formed.  Then whenever the macro is %6used%* we can
simply make a copy of this subtree and "glue" this subtree into the parse-tree
which we are building.  This computational subtree is commonly formed by passing
the body of the macro through the language processor in a slightly non-standard
 way.  The main problem with the computational macro is that there are
many desirable macros which have no such subtree, or there is other information
 necessary to process the macro.  There are solutions to this problem,
one of which closely parallels the abstract syntax ideas of McCarthy.
All of these styles of macros are subsets of the LISP macros.



.CENT(Problems)
.NL
1.##What is the difference between a special form and call-by-name
evaluation? Can call-by-name
be simulated in LISP  without redefining %3eval%*?

.P71:
.NL
2.##%3select%* is a special form to be called as: 
%3select[q;q%41%*;e%41%*;#...#;q%4n%*;e%4n%*;e]%1 and to be evaluated as follows:
%3q%* is evaluated; the %3q%4i%1's are evaluated from left to right until
one is found  with the value of %3q%*. The value of %3select%* is the value
of the corresponding %3e%4i%1. If no such %3q%4i%1 is found the value of
%3select%* is the value of %3e%1. The %3select%* 
operator is a precursor of the 
%2⊗→case statement↔←%*; see {yon(P70)}.
Add a recognizer to %3eval%* to handle %3select%* and write a function to
perform the evaluation of %3select%*. 

.NL
3.##Define %3list%*  as a macro.
.NL
4.##Extend the %3eval-apply%1 pair of {yonss(P6)} to handle macros.
.REQUIRE "NOTES.APE" SOURCE_FILE;
.REQUIRE "NOTES.IMB" SOURCE_FILE;
.SS(The %3prog%*-feature,,P37:)
.TURN ON "←";
%1
.FP
Though recursion is a significant tool for constructing LISP programs,
there is another technique for defining algorithms in LISP.  It is
an iterative style of programming which is called the
⊗→%3prog%*↔←  or %3prog%1ram feature.



.GROUP;
Many algorithms are presented more naturally as iterative
schemes.  
For example, the recursive algorithms %3length%1 and %3length%41%1, given
on {yon(P272)}, compute the length of a list.
Compare those schemes with the following:
.NL
%21.%*##Set a variable %3l1%1 to the given list.  Set a variable %3c%1 to zero.
.NL
%22.%*##If the list is empty, return 
the  current value in %3c%1 as value of the computation.
.NL
%23.%*##Otherwise, increment %3c%1 by one.
.NL
%24.%*##Set %3l1%1 to the %3rest%* of %3l1%1.
.NL
%25.%*##Go to line 2.
.PT24
.APART;

.GROUP;
.FP
Here is a LISP  version of the algorithm:
.BEGIN TABIT2(19,21);SELECT 3;GROUP;TURN OFF "←";
.BOXA
.P45:
⊗→length↔← <= λ[[l]prog[[l1;c]
\\l1 ← l;
\\c ← 0;
\a\[null[l1] → return[c]];
\\c ← c+1;
\\l1 ← rest[l1];
\\go[a]] ]
.BOXB
.END
.APART
.FP
We have introduced several new symbols, formats, and functions
in this example. These innovations must be explained before
the example is complete. First,
the basic syntax of a %3prog%1 is given by:

.BEGIN tabit2(15,23);group;turnoff "←";
.BOXA
<prog>\::= %3prog%1[[<prog variables>]<prog body>]
.PT2
<prog body>\::= <prog element><prog body> | <prog element>
.PT2
<prog element>\::= <label> | <prog form>;
.PT2
<label>\::= <identifier>
.PT2
<prog form>\::= <application> 
\::= <conditional statement> 
\::= <assignment statement>
\::= <return statement>
\::= <go statement>
.END
.BEGIN tabit2(18,26);group;turnoff "←";
.PT2
<conditional statement>\::= <conditional expression>
.PT2
<assignment statement>\::= <identifier> ← <form>
.PT2
<return statement>\::= %3return%1[<form>]
.PT2
<go statement>\::= %3go%1[<form>]
.BOXB
.END
In the example, the
variables, %3l1%* and %3c%1, are called %3prog%1#variables. They are
 ⊗→local variable↔←s, similar in behavior to λ-variables;
in most implementations the %3prog%1 variables are initialized to %3(#)%1
and we will assume this convention throughout the text.⊗↓A useful alternative
is to initialize them to some "unbound" value. In that way  the
system can recognize attempts to
select the value of a %3prog%1 variable before is has been assigned to.← 
This behavior of %3prog%1 variables can be expressed as:
.boxa
.begin center;select 3;
prog[[x%41%3; ...; x%4n%3] %9x%3] %9 ≡ %3λ[[x%41%3; ... x%4n%3]%9x%3][( ); ... ( )]
.end
.boxb
The body %9x%1 contains the imperative behavior.
The %3prog%1 body is a sequence of  %3prog%1#forms and labels.
Each  %3prog%1#form is evaluated in the usual LISP manner, and since
the %3prog%1#body can consist of a sequence of %3prog%1#forms, the
%3prog%1-body is evaluated from left-to-right.

If the intent of the %3prog%1 was simply to execute the sequence of 
%3prog%1#forms,  in left-to-right order, then %3prog%1 could  be replaced by 
a much simpler construct like %3progn%1:
.BEGIN CENTERIT;SELECT 3;
.BOXA
←%3progn <= λ[[x%41%3; ...; %3x%4n%3] %3x%4n%3]
.BOXB
.END
.FP
However we will add constructs to LISP which will allow us to
vary the flow of control within the %3prog%1#body. It is to this
end that we use labels, like %3a%1 in the example.⊗↓Labels
are also known as "tags".←  Before we discuss control structures,
 we give more details on LISP's assignment statement.

As with all LISP
constructs, the assignment  statement returns a value, 
but we identify it as a statement
since it is executed more for effect than for value.
The value  of the assignment is the value of the form
on its right-hand-side.
In our example of %3length%1, we used an assignment to bind %3l1%1 to the
value of %3l%1 and to bind %3c%1 to %30%1.
To evaluate an assignment, we first evaluate the form; then the identifier
is located by searching the access chain. Thus the identifier may be a
non-local variable. When the identifier is located its current value is %6replaced%1
by the value of the form. Notice that this is a different kind of binding than
that previously done by λ-binding. In λ-binding we always associated a new
value with a newly created local symbol table as we entered the λ-body.
We never destroyed the old binding of a variable. 
The  assigment statement involves a destructive change to the
binding. This is important since assignments 
to non-local variables can have effect outside the
%3prog%1 while a λ-rebinding cannot. 
This is how an assignment statement  can achieve a more permanent side-effect.
However, since  %3prog%1 variables are created like λ-bindings, assignments
to local %3prog%1 variables cannot effect bindings of these
variables which were made outside the scope of the current %3prog%1.
This behavior makes %3prog%1s suitable as components in recursive definitions.
For example,  a function to reverse a list and all of its sublist
can be described as:
.boxa
.begin tabit3(10,23,26);select 3;turn off "←";
\bigrev <=λ[[l] prog[\[x]
\\a\[null[l]→ return[x]];
\\\x ← concat[bigrev[first[l]];x];
\\\l ← rest[l];
\\\go[a]]]
.end
.boxb
As  the examples  have intimated, %3prog%1 introduces some new control structures
so that the %3prog%1#body need not be executed in simple left-to-right order.
The control structures are: the conditional statement, the %3return%1 statement, 
and the %3go%1 statement.

Though conditional statements in %3prog%1s have the same syntax as conditional
expressions, their semantics is slightly different. A conditional
statement is executed  in the usual manner unless none of the predicate
alternatives is satisfied. Recall that a conditional expression is undefined
in this case; a conditional statement however is defined, returns %3(#)%1,
and executes the next statement in the %3prog%1#body.
In our %3length%1 example, the expression,  
###%3[null[l1]#→#return[c]]%1### indicates that
if %3l1%1 is not empty 
the %3prog%1#body continues at the next statement with the assignment
of %3rest[l1]%1 to %3l1%1; 
the assignment destroys the old value of %3l1%1. 
If %3l1%1 %6is%1 empty, then the statement %3return[c]%1
is executed.

.BEGIN TURN OFF "←";
There is a useful interplay
between the λ-binding  of %3l%1 and the assignment binding of %3l1%1.
We could have dispensed with the %3prog%1#variable %3l1%1, and used
%3l%1 throughout the %3prog%1#body. Even the assignment %3l#←#rest[l]%1
would not have effected the binding of the original argument passed to
%3length%1. This is assured because the λ-binding saves that value
and the effect of the assignment is only to change the contents of a 
"box" whose current content is a "pointer" to the value. None of the
LISP operations we have discussed can alter a value "pointed#to" in 
this fashion. We will discuss such operations in {yonss(P171)}.
.END


The %3return%1 statement is a %3prog%1 construct similar in effect to
exiting a λ-expression. It is used to leave a %3prog%1#body and return to 
the caller of the %3prog%1. As we leave the %3prog%1, the bindings of the 
%3prog%1#variables are removed as are any λ-bindings made on entry to the %3prog%1.
The value returned is the value of the argument 
to the %3return%1 statement. The %3return%1 statement may be nested within
other LISP computation, as for example:
.BEGIN CENTER;SELECT 3;
.BOXA
concat[A;return[list[B]]] 
.BOXB
.END
.FP
The effect of the %3return%1 is  immediate;  
the %3concat%1 would never complete its operation. We would return %3(B)%1
to the caller of the enclosing %3prog%1. A bit of care is needed in describing
the meaning of %3return%1: we look for the latest instance of an entrance to
a %3prog%1 and return from that %3prog%1. To visualize this,
we use  the Weizenbaum environments#({yon(P190)}). We search the %2control chain%1, 
looking for the first %2Form%1 which is %3prog[[#...#]#...#]%1. We then restore
using the access and control information found in that diagram.
We will give a comprehensive example after discussing the %3go%1 statement.

.P83:
The %3go%1 statement is used in conjunction with labels to divert the
implied left-to-right execution of the %3prog%1#body.
Labels really aren't executed; they are used to name statements in a %3prog%1.
It is the %3go%1 statement which uses the label as a destination for transferring
control.
Labels may be in conflict with the 
λ-variables or %3prog%*#variables since the 
evaluator for %3prog%*s can resolve the
conflicts by context. Any identifier occurring by itself in a
%3prog%1#body is a label. Any identifier occurring in an application other than
a %3go%1#statement is a variable and its value is searched for in the access chain,
whereas an identifier appearing in a %3go%1 statement is interpreted as a label and
searched for in a %3prog%1 body.

The ⊗→%3go%*↔← statement is a little more complicated than the %3return%1 statement.
If the argument
to %3go%* is an identifier then it is interpreted as a label; 
otherwise, the argument
is %6evaluated%* and the result of the evaluation examined.
This process continues until
a label has been uncovered as the result of an evaluation.
At that time we must locate a
statment in a %3prog%1 which has a matching label attached to it. Our intention
is to transfer control to that statement.
We locate the labeled statement as follows:
we look through the control chain for the first %3prog%1 which contains
the label. When the label is found we transfer control to that labeled
statement, restoring the access and control environments of the %3prog%1
which contain that statement. Thus there is a double search involved:
we search the control chain for %3prog%1 forms, and search the %3prog%1 forms
for the label.
Labels need not be local; we find the closest dynamically surrounding
%3prog%1 which contains the required label. 

The non-local  %3go%1 and %3return%1 differ from the usual procedure exit 
in that they do not restore the enclosing control environment, but escape 
further back the control chain.

.GROUP;
Finally, as an example covering the new features of %3prog%1 consider:
.BEGIN  SELECT 3;tabit3(20,33,35);GROUP;turn off "←";
.BOXA
\f <= λ[[y;z] prog[[l;x]
\\\l ← 2;
\\l\u ← g[y;x;z]
\\\   ... ]]
.PT2
\g <= λ[[x;y;z] prog[[ ]
\\\ ...
\\\go[l]
\\\ ...
\\\return[first[x]]
\\\ ... ]]
.BOXB
.END
.APART
.FP
In %3f%1, %3l%1 is both a label and a %3prog%1#variable.
Notice in %3g%1 that we have no %3prog%1 variables; and since we assume
that %3l%1 is not a label in %3g%1 we have a non-local %3go%1.

.GROUP;
Consider the evaluation of %3f[(A B);3]%1.
.BEGIN TURN ON "\";NOFILL;TABS    1,6,16, 31,36,44, 49,54,64;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS    1,6,16, 27,32,40, 45,50,61,63;GROUP;>>
.TURN OFF "←";
.KRK
.BOXA
\\%3f[(A B);3]\\\prog[[l;x]...]\\[l ← 2; l u ← g[y;x;z];...]
\\%1E%40%*\\\E%41%*\\\E%42%*
\ /\| /\\ E%40%1 \|  E%40%*\\ E%41%1\|  E%41%*
\_______\=>\_______\=>\_______     =>
\%3 f  \| λ[[y;z] prog[...]]\ y\| (A B)\\ l\| ( )
\%3 g  \| λ[[x;y;z] prog[...]]\ z\| 3\\ x\| ( )
.BOXB
.END
.APART;
.BEGIN TURNOFF "←";
.group
.FP
At this point we have done the λ-binding and initialized the %3prog%1#variables.
As we begin the execution of the %3prog%1#body, we assign %32%1 to %3l%1 and,
since labels have no computational effect, begin the evaluation of the assignment
statement: %3u#←#g[y;x;z]%1:
.END
.BEGIN TURN ON "\";NOFILL;TABS  10,18,33,44,48,63;GROUP;turn off "←";
.<<BEGIN TURN ON "\";NOFILL;TABS  10,18,33,38,41,56;GROUP;turn off "←";>>
.KRK
.BOXA
\\%3[... l u ← g[y;x;z];...]\\[...u ← g[y;x;z]; ...]
\\E%42%*\\\E%42%*
\   E%41%*\| E%41%*\\ E%41%*\| E%41%*    
\    __________\=>\_________
\     %3l\| 2           \\l\| 2
\     x\| ( )           \\x\| ( )
.BOXB
.END
.apart
.GROUP
.FP
We evaluate %3g[y;x;z]%1:
.pt2;pt2
.BEGIN TURN ON "\";NOFILL;TABS  10,18,33, 44,48,63;GROUP;
.<<BEGIN TURN ON "\";NOFILL;TABS  10,18,33,38,41,56;GROUP;>>
.KRK
\\%3prog[[ ] ...]\\[...go[l]; ... return[first[x]]; ...]
\\E%43%*\\\E%44%*
\   E%42%*\| E%42%*\\ E%43%*\| E%43%*    
\    __________\=>\_________
\     %3x\| (A B) 
\     y\| ( )
\     z\| 3
.BOXB
.END
.APART
.FP
The %3go[l]%1 will search the control chain; it looks in the %3prog%1 form of
E%43%1 but finds no label %3l%1. It examines the 
%3prog%1 of E%41%1 next, and there it does
find the label %3l%1. Thus execution would be continued 
at the assignment statement using E%42%1, the
environment which bound the %3prog%1#variables.
In general, we continue in the environment which was created on entry to the
%3prog%1#body.

Notice that once we have left E%44%1 there is no
way to jump back into it.
We can only search down the control chain, and  the entry to %3g%1 is not below 
that of %3f%1 on that chain.
An extension of the  semantics of LISP could allow such generalized control
and we will develop some of those ideas in {yonss(P187)}.

.BEGIN TURNOFF "←";
If we executed the %3return[first[x]]%1 in E%44%1 an action similar to that of %3go%1
would transpire. We would evaluate %3first[x]%1, getting %3A%1. We would search the
control chain for the %6latest%1 %3prog%1#expression; here found in E%43%1;
and then return control to the environment designated in the control
quadrant; here E%42%1. Thus we return
%3A%1  as the value of %3g[y;x;z]%1. Since the call on %3g%1 was a component of
the assignment %3u#←#g[y;x;z]%1, we must complete that assignment. We search the %2access%1
chain for %3u%1. Since %3u%1 is not found we make a global assignment
in E%40%1:
.END

.BEGIN TURN ON "\";NOFILL;TABS  15,23,38,43,46,61,66;GROUP;
.BOXA
.KRK
\\E%40%*
\ \/| /%*
\______________%3
\      %3f\|  λ[[y;z] ...]
\      %3g\|  λ[[x;y;z] ...]
\      %3u\|  A
.BOXB
.END
The ability to evaluate the argument to %3go%1 results in 
a useful programming trick.  Let %3l%* be a list of dotted pairs,
each of the form, %3(%*object%4i%* . label%4i%3)%1. At each label%4i%* we
begin a piece of program to be executed when object%4i%* has been recognized.
Then the construct:
.BOXA
.P25:
%2UGH%*←%3go[cdr[assoc[x;l]]]%* 
.BOXB
.FP
can be used to "dispatch" to the  appropriate code when %3x%* is one of the
object%4i%*. This is an instance of %2⊗→table-driven↔←%* programming.
The blocks of code dispatched to can be distributed throughout the body of the
%3prog%*. Each block of code will usually be followed by a %3go%* back to
the code involving equation %2UGH%* (above). In fact the argument %3l%* in %2UGH%*
may be %6global%* to the %3prog%*-body.
The effect is to make a %3prog%* which is very difficult to understand.
The LISP %3select%* ({yon(P71)}) will handle many of the possible applications 
of this coding trick and result in a more readable program. The case-statement ({yon(P70)}) 
present in  some other languages is also a better means of handling this problem.

The %3go%1 statement is useful if used with discretion. It is a 
building block for constructing more complex control regimes, particularly since
the label need not be local to the %3prog%1
but only need be accessible through the control chain. 
We will examine some more complex
kinds of control behavior in {yonss(P187)}.

Now to the problem of translating a %3prog%* into an S-expression representation:
the construct,
.BOXA
←%3prog[[v%41%3; ...; v%4n%3]   ...  ]%1  will be translated to:
.PT2
←%3(PROG(V1 ... VN)   ...  )%*  
.BOXB
.FP
The body of the %3prog%* must be handled specially by a
new  piece of  the evaluator since
%3prog%*  is a special form.

.TURN OFF "←";

We must also be careful about the interpretation of ←.
We will write   %3x ← y%*  in prefix form: %3setq[x;y]%*. 
We will  map this to:
.BEGIN CENTER
.BOXA
%3(SETQ X Y) %*   
.END
.FP
The assignment,
 %3setq%1, is also a special form.
For if %3x%* and %3y%* have values %32%* and %33%*, for example, then the
call-by-value interpretation of %3setq[x;y]%* would say %3setq[2;3]%*. This was not our
intention.  We want to evaluate the second argument
to %3setq%1 while stopping the evaluation of the first argument.



LISP has another assignment-like operator called %3set%1.
Both arguments of this binary operator are evaluated; the value 
of the first argument is expected to be a representation of a variable;
that is, the first argument evaluates to a literal atom.
 The second argument is a LISP form
and using the value of that form, an assignment is made to the
variable represented by the first argument. Thus 
%3setq[x;y]%1 is synonymous with %3set[quote[x];y]%1.

.TURN ON "←";


As a more complex example, consider %3set[z; plus[x;1]]%1.
If the current value of
variable %3z%* is an identifier, then
%3set[z; plus[x;1]]%* makes sense.  Assume the current value of 
%3z%1  is %3A%*; and assume the current value of %3x%1 is %32%1;
since %3A%1 represents the identifier %3a%1,
the effect of the %3set%* statement is to assign the value %33%* to %3a%*.
Normally when making assignments, we want to assign to a %6name%* and
not a %6value%*; thus we will tend to use the %3setq%1 form.

.GROUP
Finally, here is a translation of the body of the %3prog%* version of %3length:%*
.P250:
%3
.BEGIN TABIT3(7,20,24);
.BOXA
\(LAMBDA\(L)
\\(PROG (L1 C)
\\\(SETQ L1 L)
\\\(SETQ C 0)
\\A\(COND ((NULL L1) (RETURN C)))
\\\(SETQ C (ADD1 C))
\\\(SETQ L1 (REST L1))
\\\(GO A) ))
.BOXB
.END
.APART
%1
Now that assignment statements have been described, let's re-examine "<=". 
We already know ({yon(P89)}) that "<=" does more than simply associate the 
right hand side with a symbol table entry of the left hand side; it must  also
associate an environment with the  function body, and this environment is to be 
used for accessing non-local variables. This operation of associating environments
is called forming the %2⊗→closure↔←%*. We thus might be tempted to say:

.BEGIN CENTER;SELECT 3;TURN OFF "←";
.BOXA
f <= λ[[ ... ] ...] %1is%*  f ← function[λ[[ ...] ...] ] 
.BOXB
.END
.FP
Alas, this implementation is still not sufficient as we will see in {yonss(P90)}.

.REQUIRE "PROB7.PUB" SOURCE_FILE;


.P259:
.GROUP;
.NL
6.##Give a macro definition of an extended %3SETQ%*, which is called 
as %3(SETQ#%1var%41%*#exp%41%*#...#var%4n%*#exp%4n%3)%1.
Each var%4i%* is a name; each exp%4i%* is an expression to be evaluated
and assigned to var%4i%1. The assignments should take effect from "left-to-right".
Thus %3(SETQ#X#2#Y#(TIMES#2#X)#X#3)%* when executed should assign
%33%* to %3X%* and %34%* to %3Y%*.
.APART;
.GROUP;
.NL
7.##Express %3setq%1 as a macro over %3set%1.
.NL
8.##Write a %3prog%1 which will terminate if call-by-value evaluation
is used, but will not terminate under call-by-name.
.NL
.P281:
9.##Use  your %3prog%1 version of %3fact%1 (prob#1,#%2b%1) and
evaluate %3fact[2]%1 using Weizenbaum diagrams. Note the difference
between the internal structures used here and the structures used
in the recursive version. This difference in implementation overhead
is a quantitive measure of the expense of recursion versus the
expense of iteration.
.APART
.REQUIRE "NOTES.EVA" SOURCE_FILE;
.SS(Function Definitions,,P202:)
.begin "fd"
.FP
Now that we have developed these more explicit evaluators, we should 
exploit some of this additional detail. In particular, more of the detail
of "<=" should be understandable. The effect of %3f#<=#λ[[x]#%9x%3]%1 is to put 
the definition
of %3f%1 in the global environment, whereas %3label%1 creates a new
dest-block with %3f%1 bound to  a %3funarg%1 consisting of %9x%1 and
that constructed environment. Once we leave the environment containing
the %3label%1 definition, that definition is effectively destroyed.
The effect of "<=" is to be global. 
A "<="-definition  could be  temporarily superseded
by a %3label%1-definition to the same name and therefore our search
for a binding for %3f%1 may not short-circuit the environment chain.

Our search strategy is encoded in the %3lookup%1 function; using
the current environment, we find the latest active binding for a variable.
The %3prog%1 evaluator, %3peval%41%1 of {yon(P203)} is a bit
more complicated. Besides finding the definition
we must also determine whether the arguments are to be evaluated.
The device of %3isspec%1 ({yon(P201)}) is sufficient for the
evaluators, but has some difficulties if we wish to allow user-defined
special forms. We will develop a syntax for expressing special forms
at the user level, and then discuss problems of implementation.

We will define
"<%4f%*=" to mean "..is defined to be a special form...".
A special-form definition is also called a %2⊗→fexpr↔←%1;
and a call-by-value definition is called an %2⊗→expr↔←%1.

A fexpr is defined with either one or two formal parameters. The first parameter
is always  bound to the 
list of %6unevaluated%* actual parameters.
If the definition has a second formal parameter, then the environment at the
point of call is assigned to the second parameter.
This distinction needs to be made if we expect to perform some evaluation of the
formal parameters within the fexpr.
Using the implementation of %3eval%1 discussed on {yon(P205)} we can write
either %3eval[%1<form>;<env>]%1 or %3eval%1[<form>]. In the latter case
the environment that is used is the environment which was current when
the %3eval%1 is performed. Sometimes this is not the desired environment.
Consider:

.BEGIN TABIT2(4,20);SELECT 3;TURN OFF "←";GROUP;
.BOXA
\f1 <%4f%*= λ[[x] prog[[y]
\\y ← 2;
\\return[eval[first[x]]]]]
.END;
.PT2
.FP
If we execute %3f1[0]%*, %3x%* will be bound to the list %3(0)%* and
%3eval[first[x]]%* will return %30%*  as expected. But if we execute:

.BEGIN TABIT2(4,21);SELECT 3;TURN OFF "←";GROUP;
.PT2
\y ← 0;
\f1[y];
.END
.BOXB
.FP
then %3x%* gets bound to %3(Y)%*, and %3eval[Y]%* will find the
value associated with %3Y%* to be %32%*, and
the value of %3f1[y]%* is %32%*,
rather than the expected %30%*. 

.GROUP;
The problem is that the call on
%3eval%* takes place in the %3prog%1 environment.
We can correct this by making the definition with %6two%1 arguments, binding
the second to the environment at the point of call to the fexpr:

.BEGIN TABIT2(4,17);SELECT 3;TURN OFF "←";GROUP;
.BOXA
\f2 <%4f%*= λ[[x;a] prog[[y]
\\y ← 2;
\\return[eval[first[x];a]]]]
.PT2
\y ← 0;
\f2[y];
.END;
.APART;
.BOXB
.GROUP;
.FP
The call on %3f2%* will use the environment with %3y%* being %30%*
rather than %32%*. 

As a final example:
.BEGIN TABIT2(4,17);SELECT 3;TURN OFF "←";GROUP;
.boxb
\f3 <%4f%*= λ[[x;a] prog[[z]
\\y ← 2;
\\return[eval[first[x];a]]]]
.PT2
\y ← 0;
\f3[y];
.END;
.BOXB
.FP
would return %32%1. 
.APART
.GROUP;
As we have just seen, special forms must be used with care.
However, they  are useful in several contexts. Recall that we restricted
LISP call-by-value functions to have a fixed number of arguments. For example
if we wish to add four  numbers or append three lists we have to write something like:
.BEGIN CENTERIT;SELECT 3;
.BOXA
←plus[x%41%3;[plus[x%42%3;plus[x%43%3;x%44%3]%1     or    %3append[append[l%41%3;l%42%3];l%43%3]
.BOXB
.END
.APART

.GROUP;
.FP
Since %3plus%1 and %3append%1 are associative operations we would rather write:
.BEGIN CENTERIT;SELECT 3;
.BOXA
←plus[x%41%3;x%42%3;x%43%3;x%44%3]%1     or     %3append[l%41%3;l%42%3;l%43%3]
.BOXB
.END
.APART;

.BEGIN SELECT 3; GROUP;TABIT2(14,16);turn off "←";
.P59:
.BEGIN FILL;SELECT 1;
We discussed the macro implementation of these constructs in {yonss(P8)}.
Using a special form, we could write %3plus%1 as:
.END
.BOXA
plus <%4f%*= λ[\[l;e] prog[[sum]
\\sum ← 0;
\a\[null[l] → return[sum]];
\\sum ← *plus[sum;eval[first[l];e]];
\\l ← rest[l];
\\go[a]]]
.BOXB
.END
.FP
Notice that we could have used %3eval%1 with one argument unless the
variables %3l%1 or %3sum%1 appeared as constitutents of the actual parameters.

.GROUP;
Recalling {yonss(P8)}, we can use <%4f%1= to extend the evaluator.
For example, %3and%* could be defined as:
.BEGIN CENTERIT;GROUP;TABIT2(20,35);
.BOXA
%3and <%4f%*= λ[[l;e] evand[l;e]]### %1where## %3evand%* is defined on {yon(P53)}.
.BOXB
.END

.APART;

The implementation of %3g#<%4f%1=#%3λ[[x]#%9x%1]  requires that we represent the
fact that %3g%1 is a fexpr rather than an expr. The implication of
%3isspec%1 of {yon(P201)} is that we have two tables: one for exprs,
one for fexprs. This complicates the search strategy unnecessarily.
Indeed there should only be one definition or value associated with 
a name at any one time, so a single table should be both
necessary and sufficient. We %6do%1 need some way of determining
the calling style to be used when applying the definition.
One way is to revise the %3isspec%1 technique slightly: we use %3lookup%1
for %6all%1 searches, but also have a table relating function-name
with its calling style. One difficulty with this scheme is that
we could not handle anonymous fexpr definitions. Therefore
some versions of LISP replace the character "λ" with another special
character when making fexpr definitions. For example:
.BEGIN CENTER;SELECT 3;
g <%4f%3= λ[[x;y] %9x%3] %9≡%3  g <= β[[x;y] %9x%3]
.END
We  would translate such β-expressions into S-expr form,
 and extend the evaluator to recognize such constructs.


We could use a similar technique to recognize macro definitions.
The next chapter will discuss some alternative implementations.


.CENT(Problems)
.NL
1.##Define %3list%* as a special form.
.NL
2.##Write a version of %3peval%1 to handle β-expressions.
.NL
.GROUP;
3.##Define two special forms, %3de%1 and %3df%1, which will 
implement <= and <%4f%1= respectively. The format of these special
forms is identical. For example: 
.BEGIN CENTER;
%3de%1[<name>;<formal#parameters>;<body>]
.END
.ONCE INDENT 4,4
will implement 
.BEGIN CENTER;
<name> <= λ[<formal parameters> <body>]
.END
.APART
.end "FD"
.SS(Rapprochement: In Retrospect,,P90:)
.BEGIN "RAP"
.FP
As with the  review section of the previous chapter, this section
is a mixture of the practical and the theoretical.  That is a healthy
attitude to cultivate when discussing programming languages.
For example, in the first section of this chapter we claimed that
a theoretically expected relationship between call-by-name and
call-by-value breaks down in the presence of side-effects.
The idea of side-effects is a decidedly  practical one, based on the 
"practical" notion
of a "variable" as a "box which contains a value", rather than the
mathematical notion of a "variable" as a  description for an
anonymous, but fixed, element of a domain.

.BEGIN GROUP;TURN OFF "←";
.P278:
Consider the following expression:
.SELECT 3; TABIT3(20,27,30);
.BOXA
\prog [[ ]\y ← 0;
\\λ[[x] prog[[ ]
\\\loop\[eq[y;0] → go[loop]] 
\\ [y ← 1]]]]
.BOXB
.FILL;SELECT 1;
.FP
If this expression is evaluated using call-by-value, we bind %3y%1 to %30%1,
and evaluate the anonymous λ-expression. That entails evaluation of
%3y#←#1%1, %6before%1  entering the %3prog%1. The computation of the
%3prog%1#body terminates, returning %3NIL%1.
Call-by-name evaluation  would not evaluate %3y#←#1%1  and the computation
would not terminate.
.END


The issue of side-effects highlights an important distinction between
"variables" in the mathematical sense and "variables" in the programming sense.
In mathematics, we use the term, variable, to designate a fixed, but anonymous,
object: "let %3x%1 be a real number#...". In programming languages,
an object is "variable" as opposed to a "constant", meaning that the quantity
associated with the object may vary. Thus the idea of "box which contains a value"
arises again. The manipulation of variables in languages leads to further
distinctions. 

Applicative languages, modelled after the %9λ%1-calculus,
simulate the reduction rules by associating an environment or symbol table
with an expression. What is being simulated is a "copy#rule" which
says that the  reduction is to be done by making a copy of the expression,  
substituting the actual parameters into the copy wherever one of the %9λ%1-variables
appeared in the original expression. The effect of the symbol table is to
%6share%1 a common instance of the actual parameter. The idea of sharing
becomes  central when we discuss assignments and the behavior of side-effects.
If %6copies%1 of values are made, the issue of side-effects vanishes.
Important distinctions arise
when we are able  both to %6share%1  values and
to destructively %6change%1 values. This combination  of properties is present
in the general assignment  statement.  Because of the close relationship
between assignment and LISP's λ-binding, λ-binding is sometimes
called a "pushdown" assignment (⊗↑[New#61]↑), as compared with a "destructive"
assignment.
The adjective, "pushdown", refers to the λ-binding's ability to save the
prior binding of a λ-variable in such a way that it may be restored
after the computation is completed. 

Differences in binding are highlighted by the implementation of %3function%1.
In the applicative subset, %3function%1 is  satisfactorily implemented by
the %3FUNARG%1 triple, where the  substitution  is represented by 
a pointer to the binding environment. In the presence of assignment statements,
this equivalence breaks down.
.GROUP;
Consider the following example due to H. Samet:

.BEGIN TABIT2(10,28);turn off "←";
.BOXA
\%3f <= λ[[x] prog\[[]
\\ a ← a+1;
\\ return[[eq[a;1] → x; %et%3 → -x]]]]
.END
.APART;
.PT2
.GROUP;
.BEGIN TABIT2(10,31);turn off "←";
\%3g <= λ[[x;fun] prog\[[]
\\ a ← 0;
\\ return[fun[x]]]]
.boxb
%1Now evaluate  %3h[1]%1   where  %3h <= λ[[a] g[3;function[f]]]%1
.BOXB
.END
.APART;
.fp
If we implemented %3function%1 as a direct substitution of values
for free variables, then %3h[1]%1 would yield %3-3%1.
The implementation of %3function%1 as a pointer to the binding environment
yields %33%1.
It is clear where the problem lies; we have assigned to a non-local variable
after the substitution would have been carried out.
However, compare the current situation with the example on {yon(P94)}.
The lesson to be learned is that assignment statements do not fit well with  the
 substitution model.

We  enriched the LISP subset to allow such constructs as 
iteration and assignment;
 therefore, we  wished to provide an evaluator which
adequately reflected the implementation, or pragmatics,
of these facilities. We could have  modelled them directly in the initial
LISP subset, but the representation would not  convey the intended
implementation. As a result, we developed an interpreter which
directly modelled  the  assignment statements, %3return%1 statements,
and non-local %3go%1 statements. These are some of the most troublesome
areas to  reflect in an applicative model.

The result of our investigations was  %3peval%1. This evaluator
expresses the implementation of the enriched subset of LISP; it 
is self-explanatory in the sense that  any construct which %3peval%1
uses has a data structure representation which is recognizable by %3peval%1.
That is, %3peval%1 can interpret   expressions involving representations
of %3peval%1.

The process of developing %3peval%1  exposed the control structure of LISP
just as the development of %3eval%1 in {yonsec(P113)} exposed
the access structure. A data structure model  for
access environments  was necessary since the implementation of %3function%1
demanded it. Traditional LISP does not allow such generality in the area of
control structure.
The appearance of non-local %3go%1s and %3return%1s requires
control behavior analogous to that of functional arguments, but control regimes
analogous to that of functional %6values%1 do not appear
in LISP. More recent demands
from LISP users have  prompted development of generalized
control structures in LISP-like languages (⊗↑[Hew#72]↑, ⊗↑[Pre#72]↑, ⊗↑[Pre#76a]↑,
⊗↑[Bob#73a]↑, ⊗↑[Con#73]↑). Now that we have developed the data structure
representation for control, we could  extend LISP to  allow
 manipulation of control structures. We resist that temptation,
leaving such experimentation to the reader.

As we have just seen there are 
alternatives to some of the LISP-techniques and there are some things
which, in retrospect, LISP could have done better.
There are some
conceptual difficulties with LISP evaluation.
We have seen some  computational schemes which
will give values when LISP's call-by-value does not terminate.
Whether these schemes are better is a debatable point.
Programmers tend to think "call-by-value," but  it is not clear 
whether that is habit,
training, or a fundamental point of view towards computation.⊗↓Compare
⊗↑[And#76]↑  in discussing call-by-name versus call-by-value: 
"programs which don't terminate usually have bugs, and 
programmers would rather find out sooner (call-by-value) than later
(call-by-name)".← 

The practical and the theoretical aspects of programming languages have
much common ground.
As we have seen, the notion of "function" 
in mathematics is different from the notion
of "LISP function." The former is a set-theoretic notion, the latter is
an algorithmic notion. With the introduction of iteration, a further
discrimination is needed.
A useful classification  of "recursive" appears in ⊗↑[Hew#76]↑.

.BEGIN GROUP;
.NL
%21.%1##"Recursive" in the sense of recursive function theory (⊗↑[Rog#67]↑)
meaning that there is an algorithm which specifies the function.
This involves a precise study of the concepts of algorithm and computability.
.apart
.group;
.NL
%22.%1##"Recursive" in the sense of self-referential. The definition
of an algorithm  makes reference to the algorithm itself.
The idea of "self-reference" needs to be  handled carefully.
The definition may involve  mutual recursion: %3f%1 calls %3g%1, and %3g%1
calls %3f%1. Also, we saw on {yon(P99)} that  a function may be
dynamically self-referential, while the static text is not.
.apart
.group;
.NL
%23.%1##Finally, "recursive" is used  meaning "non-iterative".
This is the usual interpretation imposed in programming languages.
This sense implies some assumptions about the   evaluation implementation.
Basically, it is to mean that  a recursive evaluation will require
more bookkeeping than the iterative evaluation. 
A problem on {yon(P281)} asked for an iterative evaluation of
%3fact[2]%1; fewer environments were created there than we required
for the evaluation of the "recursive" (in the sense of %22%1) version.
This third use of the word "recursive" is the least well defined and understood.
It is frequently believed that "recursive" in the sense of %22%1
implies  the third "recursive." The third sense is more a property of the
implementation of the evaluation scheme than a property of the algorithm.
Techniques are know for evaluating several classes of "recursive"
algorithms using iterative storage requirements; ⊗↑[Hew#76]↑,
⊗↑[Sus#76]↑, ⊗↑[Gre#76a]↑.
.apart
.END
.PT18
Since the ideas involved in "recursive" are so important to LISP
and programming languages in general, we want to explore the ideas
further.  We will be most concerned with "recursive" in sense %22%1;
we want to understand what is involved in giving a recursive definition.
We now have three ways to define functions: the %3label%1 operator,
the "<="-operator, and the assignment statement. We need to understand
the differences between these operations.

.BEGIN GROUP;TURN OFF "←";
To begin with, we were able to give
counterexamples to interpreting:
.BEGIN CENTER;turn off "←";
.BOXA
%3f <= λ[[x] %9x%1]### as### %3f ← λ[[x] %9x%3] 
.BOXB
.END
The discussion of binding and environments made %3f#←#function[λ[[x]#%9x%3]]%1
a more likely candidate; however this interpretation is also not adequate.
.END

.GROUP

.BEGIN nofill
.PT2
We might implement ##%3fact <= λ[[x][x=0 → 1; %et%* → *[x;fact[x-1]]]]%1 as:
.END
.PT2
.BEGIN CENTER;SELECT 3;TURN OFF "←";

fact ← function[λ[[x] ... fact[x-1] ...]
.BOXB
.END
.APART

.BEGIN TABIT3(10,14,18);GROUP;turn off "←";
Consider an initial environment with %3fact%1 defined:
.PT2
\\E%4i%*
\E%4c%*\|\E%4a%*
\___________
\%3fact%*\| %3λ[[x] ... fact[x-1] ... ] %1: E%4i%*
.BOXB
.apart;
.GROUP;
.BEGIN FILL;
.P276:
.FP
We will demonstrate the inadequacy of two natural interpretations of function
values: direct assignment of value, and assignment of %3funarg%1.
We execute %3foo ← fact%* and %3baz ← function[fact]%1, giving:
.END
.PT2
\\E%4i%*
\E%4c%*\|\E%4a%*
\___________
\%3fact%*\| %3λ[[x] ... fact[x-1] ... ] %1: E%4i%*
\%3foo%*\| %3λ[[x] ... fact[x-1] ... ] %1: E%4i%*
\%3baz%*\| %3fact %1: E%4i%*
.BOXB
.APART
.GROUP

.BEGIN TURN ON "#";TURN OFF "←";fill
.FP
Things don't look quite right; the "intent" of both 
%3foo#←#fact%* and %3baz#←#function[fact]%1
was to make %3foo%*  and %3baz%1 synonymous with %3fact%*. That clearly is not the case
though  the right thing happens if we were now to evaluate an expression
involving %3foo%* or %3baz%1. The problem is that it happens for the wrong reason
even though the occurrence
of %3fact%* in the body of %3foo%* will find the right definition of %3fact%*;
an application of %3baz%1 will find the definition of %3fact%1.

One more step will lead to disaster: %3fact#←#λ[[x] x]%* 
.END
.PT2
\\E%4i%*
\E%4c%*\|\E%4a%*
\___________
\%3fact%*\| %3λ[[x]x]
\%3foo%*\| %3λ[[x] ... fact[x-1] ... ] %1: E%4i%*
\%3baz%*\| %3fact %1: E%4i%*
.END
.BOXB
.BEGIN FILL;
.FP
Now we are really lost. Though it is reasonable to redefine %3fact%*
--#it is only a name#-- our intent was to keep %3baz%1 and %3foo%* as  realizations
of the factorial function. This intent has not been maintained.
.BEGIN CENTER;
.PT2
%3fact%* <= %3λ[[x] ... fact[x-1] ... ]%1 is quite different from:
.PT2
%3foo%* <= %3λ[[x] ... fact[x-1] ... ]   ⊗↓%1In LISP 1 (⊗↑[McC#60]↑)  considerations
were given to representing recursive definitions as circular structure, instead
of referring to the name. That would have solved the current problem.←
.END
.SELECT 1;
.FP
To  understand what has happened  we
look at assignments to %6simple%*
variables rather than functional variables. It is clear how the environment
should change during the execution of the sequence:
.END

.BEGIN TABIT1(10);TURN OFF "←";SELECT 3;GROUP;
.BOXA
\x ← 3
.PT2
\y ← x
.PT2
\x ← 4
.END
.FP
.BOXB
Let's try something slightly more complicated:
.BEGIN TABIT1(10);TURN OFF "←";SELECT 3;GROUP;
.PT2
\x ← 1
\x ← x%82%* - 6
.END
.FP
Here we first assign %31%* to %3x%*; then   we  evaluate the right 
hand side of the next statement. We look up the current value of %3x%*,
perform the arithmetic computations, and finally assign the value %3-5%*
to %3x%*. Compare %6this%* to the %3fact%* definition; there we made a point
of not "evaluating" the name %3fact%* in the right hand side of "<=".

.P109:
.BEGIN TURN ON "#";TURN OFF "←";
Notice that %6after%* an assignment like %3y#←#x%* has been executed, then
equality holds between the left-hand and right-hand quantities.
Let's look more closely at the relationship between "←" and "=".
Consider %3x#←#x%82%*#-#6%1. After the assignment is made, equality
does %6not%* hold between left- and right-hand sides.
Now consider %3x#=#x%82%*#-#6%1.
Interpreting this expression as an equation, not as an expression
whose value is true or false depending on the current value of %3x%*, we find
two solutions: let %3x%* have value %3-2%* or %33%*.
If we examine our "definition" of %3fact%* in %6this%* light, interpreting
"<=" as  being related to "=" rather than "←", then we are faced with an equation
to be solved, only now the form of the solution is a %6function%* which satisfies
the equation. There may be many solutions; there may be no  non-trivial solutions.
In  our case there is at least one solution: the usual factorial function.
So what we %6should%* write is something more like:
.BEGIN CENTER;SELECT 3;
.PT2
fact ← %1a solution to the equation%*: f = λ[[x][x=0 → 1; %et%* → *[x;f[x-1]]]].
.PT2
.END
.END
.FP
That is,
the %6real%* intent of the recursive definition of %3fact%* was to define a
function to effect the computation of factorial and then to %6name%* that
function %3fact%*. 
Questions of when solutions exist, how many, and which are the "best" 
solutions is a topic of much current research (⊗↑[Man#74]↑).

.REQUIRE "NOTES.IME" SOURCE_FILE;

.BEGIN TURN OFF "←";
In summary, 
LISP has two ways of assigning values to functions: %3label%1 and <=.
The use of %3label%1 manufactures a new "knotted" environment but 
does not always find the mimimal solution ⊗↑[Gor#73]↑.
The evaluation of %3f#<=#%9f%1 is interpreted as %3f#←#%9f%1, where
the assignment is made in the global environment.
LISP's solutions are sufficient for most definitions, but
a more general treatment of the ideas involved in  function definitions is
needed from both practical and theoretical considerations.
.END

A mathematical treatment of the imperative features of programming languages
requires  an extension of our model. An essential ingredient of imperatives
is their ability to  produce side-effects. This is usually modelled by
including some notion of "the state of the machine". In such a 
development, the
%7D%1 function is specified in terms of an expression, an environment, 
and a state.  


.CENT(Problems);
.NL
1.##The %3foo-fact-baz%1 example of {YON(P276)}  
is not described directly in LISP. Can you write a  LISP 
program without %3prog%1s which will also exemplify this difficulty?
.END "RAP"
.ss(LISP Machines,,P175:)
.BEGIN "LM"
.EP
"in the beginning was the Word"  
.PT24
.BEGIN TURN ON"→";
→John, %31:1%1########
.END
.EP
"in the beginning was the Word all right, but it wasn't a fixed number of bits"
.PT24
.BEGIN TURN ON"→";
→R. S. Barton, %3Software Engineering%1########
.END
.PT24
.PT24
.PT2

.FP
The LISP definitions and expressions which we have been writing are expressed
in a language  called the %2⊗→meta-language↔←%1, and
the LISP expressions  are called ⊗→M-expressions↔← or M-exprs.
The most primitive data structures of LISP  are called S-expressions.
We have seen that it is possible to represent M-expressions as S-expressions,
and
indeed, that significant results are obtained from such a mapping.
The %2programming language%*, LISP, uses the S-expr translation
of the LISP algorithms.
As we move from the  more formal aspects of LISP to the practical
details of implementations, we should reflect on  some of
the features of LISP which make it  a unique programming language.

The arguments to LISP programs are S-exprs and since we are writing
LISP programs in S-expr form, then   data and program are 
indistinguishable.
Programs must have a very special structure,
but program and data are both S-exprs just as in most hardware machines 
the contents of locations  which contain data are not distinguishable
from locations which contain instructions.⊗↓A few machines %6have%1
been built to enforce a dichotomy between data and program; the
HP3000 and several of the Burroughs machines (⊗↑[Org#73]↑, ⊗↑[Dor#76]↑) follow this
approach.← 
On  a typical contemporary machine it is the way in which a location is accessed
which determines the interpretation given to the location.
If a  processor accesses the location via the program 
counter, the contents are executed as an instruction.  That same
location can usually be accessed as part of a data manipulating 
instruction.  In that case, the contents are simply taken to be data.
LISP is one of the few high-level languages which also has this 
property⊗↓The IPL series of languages (⊗↑[New#61]↑)  had this
property, however those languages were more reminiscent of assembly
language.←
It gives the programmer exceptional power.

Since the next three chapters delve more deeply into implementation
details and machine organization, it is useful to illuminate the similarities
between LISP machines and traditional computers;
The similarities are striking.  A contemporary machine
is a computer which executes well-behaved  
programs segments referencing
very well-behaved data structures. A LISP architecture, catering
 to program debugging, has a different emphasis. 
We will see the  traditional design as a specialization of a LISP
design. 

.GROUP;
Our discussion will be restricted to common features of contemporary
computers; we will not single out one specific architecture.⊗↓Readers
who are familiar with computer architecture may find much of this discussion
too simple; however our discussions %6will%1 show  relationships
between LISP and other architectures, and  raise some interesting questions
about machine design.←
The basic item of information in the  computer will be the %2word%1;
That word will consist of binary bits, zero and one:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.boxa
.krk

		        ⊂ααααααααααα⊃
		        ~ 01 ... 10 ~
		        %ααααααααααα$

.boxb
.END
.APART
The number of bits in a word will not be too relevant for this discussion, however
we will assume that  each  word contains the
same number of bits.  The "word" is our basic unit of data.
Since programs will be specified as collections of words,
it will be convenient 
to introduce an information unit for program representation.

In most machines, the words are not simply  scattered about like loose
paper on a desk top. Rather, they are arranged neatly 
like the pages in a book. Each word has an associated   number called
a  its %2location%1.
We will call a sequential collection of computer words a %2vector%1.
For example:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.boxa;krk
		        ⊂αααααααααα⊃
		  100   ~ 10 ... 1 ~
		        εααααααααααλ
		  101   ~ 01 ... 1 ~
		        εααααααααααλ
			   ...
		        εααααααααααλ 
		  111   ~ 11 ... 0 ~
		        εααααααααααλ
		 1000   ~ 10 ... 1 ~
		        εααααααααααλ
			     ...

.boxb
.END
The numbers preceeding the words are the locations of the
words. In this example we have sketched the vector from locations
%34%48%1 through %310%48%1#.⊗↓The notation "%2i%48%1" denotes
the base
eight, or "octal", representation of %2i%1.
In the remainder of this section, any numeral
is  an octal numeral.← 
A program will be stored in memory as a vector of numbers.

Over this simple matrix of words and vectors  the computer industry
 has presented a myriad of
representations for instructions and  data items.
A ubiquitous feature is the execution cycle of a stored program machine.

For simplicity,
we will assume that the architecure is a single-address instruction
machine. This implies that each instruction of our machine will
specify two parts; an operation, and a single operand.
   Since many operations we wish to perform
expect two operands, the address format may
reference an implicit operand. That operand,
named %2AC%1, is a special register in the machine.
For example, an instruction %3ADD#100%1 would mean form the sum of the
number represented in location 100 and the number represented in 
%2AC%1,  and place the summation back in %2AC%1.⊗↓Actually
the operation "%3ADD%1" will not appear in   the memory;
rather, a bit-pattern will appear there and the computer
must interpret that pattern to mean "%3ADD%1".←  Thus the result of the
addition is "accumulated" in %2AC%1; %2AC%1 is also called the
"accumulator."  
Or %3JMZ#101%1 might
mean "begin execution at location %3101%1 if the contents
of %2AC%1 is a representation of zero; otherwise execute the
instruction following the %3JMZ%1."
We will postpone more detailed examination of specific machine instructions
until {yonsec(P107)}.
We wish to concentrate on the mechanisms which a computer uses to
execute a program.

The %2program counter%1, denoted by %2PC%1, is used
to control the execution path of a program. If %2PC%1 references
an instruction like the %3ADD%1 above, then the machine executes the addition
and then prepares to execute the next instruction in the sequence. 
The details of the %3JMZ%1
are a bit more complicated. If the contents of the %2AC%1 is  (a representation 
of) zero then the machine will place %3101%1 in the %2PC%1
so that it can execute the instruction in location %3101%1; otherwise
the instruction following the %3JMZ%1 is executed.
Our intent should be clearer now, but we can do better  with a 
diagram. Something like:
.BEGIN TABIT2(27,30);GROUP;TURN OFF "←";
.boxa
\%2l:%3\C(%2IR%3) ← C(C(%2PC%3))
\\C(%2PC%3) ← C(%2PC%3) + 1
\\ %2execute %3C(%2IR%3)
\\%2go to l
.boxb
.END
.begin turn off "←";

The  notation,
%3C(x)%1, is read "contents of %3x%1"; the arrow "←" is read "replaced by".
The %2IR%*, or %2Instruction register%1, is an internal register 
used to hold the instruction we are to execute. 
So step-by-step the diagram reads: "the contents of %2IR%1 are replaced
by the contents of the contents of %2PC%1"; that gets the next instruction.
Next, "contents of %2PC%1 are replaced by contents of %2PC%1 plus %31%1.
Note that %2PC%*
 is incremented %6before%* execution of the instruction. If we
incremented %2PC%1 %6after%1 the execution
of the instruction, and the instruction were a %3JMZ%1-type
instruction, then the %2PC%1 might get a spurious incrementation.
Finally we execute the instruction and then go back to fetch  
the next instruction. Embellishments of this
basic cycle will get us to  a LISP machine.
.end

We will assume that
any such word can contain an instruction or data,
and  the interpretation of a word
depends on the way the execution mechanism of the machine accesses the word.
For example, the contents of a location can be used both as an instruction
and as data; if location %3101%1 contained the representation of the
instruction %3ADD#101%1, then  the execution cycle for that instruction would
involve location %3101%1 in both roles; instruction %6and%1 data.
This dual role of instruction and data occurs in less ad hoc situations.
An assembler converts an external string of characters into a vector of
bit patterns which a loader finally converts into real machine instructions.
Many of the bit patterns which the loader receives from an assembler are
simply machine "instructions", however the loader acts on them as data items;
it does not execute them.


Several machines allow certain  embellishments of the operand field of
an instruction;  indirect addressing is one example. If an operand is
fetched indirectly, that means that contents of the operand field
are not used directly as data, but are interpreted as a further address
and the contents of that further address are examined. If the machine
allows  arbitrarily deep indirect addressing, that further address
is examined to see if it specifies additional indirection.
This chain of indirect addressing must terminate with a "real" address
if the instruction which instigated this mess is ever to complete
its execution.

For example, 
let a modifier %3i%1 indicate indirect addressing;
then %3ADD#10#i%1 means  don't add the contents of location %310%1
to %2AC%1 but look at the contents of location %310%1 to determine
the address. If the contents of location %310%1 is %32%1, then the contents of
location %32%1
will be added to %2AC%1.
If location %310%1 contained %32#i%1, then 
indirect cycle continues and the contents
of location %32%1 would be inspected for an address.
However if the contents of location %310%1 is %310#i%1, then we
will continue to fetch the contents of location %310%1,
looking for an operand which will not be forthcoming. 

We should 
examine several of the  conventions of this machine, asking
if they are fundamental to the architecture or are more whims or historical
accidents. After all the original Von#Neumann machines were numerically 
oriented.⊗↓⊗↑[Car#75]↑ is   interesting paper on the practical design
proposed by Alan Turing (of the theoretical Turing machine fame); 
Turing's machine had a much more non-numerical flavor.←
Why should data be numerical? Why should the instructions be sequential?
Why do we need accumulators? Let's  examine indirect 
addressing more closely.

Indirect addressing is actually a special case of an interesting idea:
instead of requiring that the operand  be a data item, let the
operand specify a further operation. There are several problems
with this scheme, none of which are insurmountable as we shall see.
However, the most important problem for our current concerns
is: if an operand may specify a further operation, then we must
have a way of terminating the "get-new-operand" fetch. We saw two
solutions in the indirect address paradigm:
.nl
%21.%1##An instruction will not invoke indirection if the %3i%1 modifier
is not present in the instruction.
.nl
%22.%1##An indirect addressing cycle will terminate 
the operand fetch when it comes across
a reference which does %2not%1 contain the %3i%1 modifier.
.boxb
These two solutions generalize nicely:
.nl
%21.%1##Have operations which look no  further. That is, their operand 
may %2look%1 like  an operation, but it is not to be taken as such in the
current context.  This is the effect of the %3quote%1 operator.
.pt2;pt2
For example:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.boxa;krk

		        ⊂ααααααααααα⊃
		 loc    ~ ADD   loc ~
		        %ααααααααααα$

.boxb
.END
When we execute %bloc%1, we also access %bloc%1 as data.
.nl
%22.%1##Supply each word with an indicator that distinguishes  data 
from instruction. The operand fetch would terminate when a "real"
operand was fetched.

As we have already  noted, some machines do supply a data-instruction
indicator (though not for the purpose we have ascribed to it);
and as we have further noted, we do %2not%1 plan to follow this policy.
The freedom to 
move freely between data and instruction is  very powerful, albeit
dangerous.
We would like uniform access to program elements and data elements. That is,
an instruction can reference either data locations or instruction locations.
In terms of our current machine this means:
.BEGIN GROUP;INDENT 5,5,5;
.boxa
If a location is referenced by the %2PC%1 then its contents is decoded
as an instruction. If a location is referenced as an operand then its
contents is taken as data.
.boxb
.END

We want similar flexibility in a LISP machine. What "arbitrary" decisions
in the current architecture should we replace?
 The data items are particularly puny.
 As an initial generalization, we might
consider a "vector" machine. Here, the basic data units would be 
vectors of    numbers. The would lead to an interesting
generalization: the %3ADD%1 operation might now specify the 
component-wise addition of two vectors, etc...#. Also programs
would be representable as data items, since they are vectors.
That's some improvement.⊗↓This generalization is similar to
that  available in  APL.←  But 
data and programs are still represented linearly, and the data items
are all representations of numbers. Surely we can do better.

First, realize that most programs are %6not%1 linear; they typically have
jumps and subroutine calls. A linearity is imposed on program structure
because of the gratuitous incrementation of the program counter.
That linearity becomes  particularly bothersome when one has to patch
machine language programs.
Note  also that much data is non-numerical
in nature; and much of that information has more complex structure than that
supplied by a "vector" machine. 
"Ah, Hah!", you exclaim; we might want vectors, of vectors, of ...#vectors,
 because that's a more general structuring of data and could be used
to reflect the non-linear structure of programs, and#... 

Excellent! Now you're ready for a LISP machine!

 
The  processor of a "LISP machine" is  ⊗→%3eval%*↔←.⊗↓Several "LISP machines"
have been proposed or actually built including: ⊗↑[Got#74]↑, 
⊗↑[Gre#74]↑, ⊗↑[Deu#73]↑, and ⊗↑[Bar#71]↑←
If %3eval%* references an S-expr via its "program counter", then 
that S-expr is decoded via the internals of %3eval%*.  If an S-expr is
referenced as an argument, then it is
taken as data.⊗↓This goes for %3funarg%1s as well: until they're applied,
they're data.←   The identity of program and data is not fixed even within
the execution; a LISP program can create a data structure which can then
be executed  either  explicitly, by appearing as an argument to %3eval%1, 
or implicitly,
by appearing in the function-position of an application.
A LISP machine is a generalization of the simple computer.
The operations which get the next instruction or get the next data
object, are more complex since neither program nor data is sequentially
related.  The next chapters will discuss implementations of LISP 
structures on traditional computers.

.GROUP;
The simplest way to communicate with such a machine is to read an
S-expr translation of a LISP expression into memory, evaluate the expression, and
print the result. Several implementations of LISP use a variant
of this  "%3read-eval-print%1" loop:

.BEGIN SELECT 3;TABIT3(13,18,20);GROUP;
.BOXA
\prog[[]
\\a\print[eval[read[];( )]];
\\\go[a]] 
.BOXB
.END
.APART
.fp
Note the similarity with  %3loop%1 on 
{yon(P208)} and the basic execution cycle of our
simple computer.⊗↓The details of %3read%1 and %3print%1, two
of the input and output operations 
in LISP, are discussed in the next chapter.← 

.P132:
A   LISP  machine is a calculator using
list-notation
input and  converting the output from LISP programs 
to list-notation wherever possible.
But internally, all manipulations are done on the S-expression
representation.
LISP will allow you to manipulate the %6representation%*
of the lists.  The LISP S-expr operations like %3car, cdr%*, and
%3cons%* operate without complaint on lists, even though we have
repeatedly said that these functions are S-expression functions.
LISP's attitude  toward %3car%1 and %3cdr%1 is similar to its
treatment of %3go%1s and labels: these are useful primitives from which
to build  tools.

One effect of this  generality is to present the  unwary
LISP user with an incredible potentiality for generating programming errors.
The alternative, to require declarations for all data objects and disallow
run time modifications to programs offers a debugging tool of some power.
If we
write programs such that the type of each data object must be given,⊗↓For example,
in {yonss(P41)} the types of the arguments to %3diff%* should be <poly> and
<variable>, %6not%* list and atom.← 
and if we write each function such that the process of binding arguments
to values must check that the type of the actual parameter agrees with
the type of the parameter of the function, then a very large number
of programming errors can be located almost as soon as they occur.
You can think of the parameter-passing mechanism as  a "fire-wall,"
which will help contain the deviant behavior to within the particular
function. 

Any function which gets called has a right to expect
that it will be called with reasonable values. Part of being
reasonable is having the correct number of arguments given to it;
%3cons[A;#B;#C]%* is as bad as %3cons[A]%*. Part of being reasonable
is having the right kind of arguments; we don't expect  results
from %3sub1[A]%*.
We should not expect that the  functions are sufficiently omniscient
to convert an argument of the wrong kind into a proper one.
If a function is written to expect an argument of type %3polynomial%*
then it should complain if it receives an argument of type
%3list%* even though the current representation for polynomials
might be special instances of lists.

Many programming languages %6do%1  offer such omniscience. Fortran
calls this service "conversion"; Algol68 calls it %2"⊗→coercion↔←"%*.
However if
 each function  accepts whatever argument
it is given and attempts to use it in its computation, then the first
indication of trouble will occur when a primitive function is called and
causes some error deep within the implementation.
Typically this indication of error is way past
the actual source of the difficulty. 
The alternative is to
explicitly code tests into the entry code of each function definition;
but
that's an expensive use of the programmer's time and  computation time.
What typically happens is that the tests are left out and 
intensive debugging
soon follows.

As with most areas of programming, coercion is not a black-or-white issue.
A strong type structure can hinder as well as help. Requiring explicit
declarations and directions for conversion is frequently annoying.
Several important programming tasks are type-free. In particular, the
debugging programs must be able to  freely access all parts of the representation
of program and data without regard for type.
To make debugging meaningful, such programs must %6modify%1 existing structures,
changing data structures and programs. 
When dealing with large complex computations,
it is not acceptable to edit programs, recompile them, and reinitialize the
whole computation. More sophisticated debugging techniques must be developed.

LISP's position is that it is the user's responsibility to handle
all type restrictions by programmed tests.
LISP  has no capability to
maintain abstract data structures; in fact, the implementation of LISP
itself is open to programmer modification.   However
people have begun investigations of "typed LISP" ⊗↑[Car#76]↑, and 
some implementations of LISP ⊗↑[Int#75]↑ give some aids
in constructing  and maintaining typed data structures.

Symbolic expressions are the only real data structure; we almost
have sequences as a data structure, and the necessary ingredients
are there to build abstract data structures. But the question of
integrity in using such defined data structures is left  in the
hands of the programmer. In summary, LISP is an excellent tool for building
more complex systems;    as a tool, it has the ability to cause
injury, and since it is a tool it has few
preconceptions. These are some of the reasons that LISP has maintained
its position as the "machine language" for Artificial Intelligence.
.end "LM"
.SEC(The Static Structure of LISP,Static Structure,,P188:)
.begin "intro"
.TURN ON "←","α";
%1
.SS(Introduction)
.FP
The material in the previous chapters has been rather abstract.
This chapter begins a discussion of the  mechanisms which
occur in implementations of LISP. However the importance of the
techniques we will describe extends far beyond the implementation of
this particular language. Most of the ideas involved in our implementation
are now considered standard system programming techniques and
are common tools in language design. LISP is  particularly well-suited
to the task of  explicating these ideas since many find their origins in 
the first LISP implementation.

We will begin our discussion of implementation with an analysis of 
storage regimes for S-expressions. As with the more abstract discussions 
of representations,
the "concrete" representation which we pick for our data structures (S-expressions)
will have direct bearing on the implementation of the primitive constructor
(%3cons%*), selectors (%3car, cdr%*) and predicates (%3atom, eq%*) of LISP.
We must also consider the efficiency of the implementation
and we must
include input and output mechanisms to translate this representation 
back and forth between the external S-expr notation.

The present chapter will develop a picture
 of the %6static%* structure of an implementation, or to be more
graphic, this chapter describes the memory of a LISP machine.
The next chapter discusses the %6dynamic structure%* of LISP;
that is, the control structures necessary to
evaluate expressions involving recursive functions and  other LISP
control constructs.

Throughout these discussions we will remain as abstract as
possible without losing too much detail.
We will 
describe the "logical" structure of a LISP machine, even though
a more efficient implementation might map differing logical structures onto
the same physical structures by utilizing machine-dependent techniques.

.end "intro"
.SS(Representation of S-expressions)
.begin "sexpr"
.FP
We previously have expressed the dotted pair %3(A#. (B#.#C))%* as:

.BEGIN SELECT g;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
		    /\ 
		   /  \
		  /   /\
		 /   /  \
		∞3A∞*   ∞3B∞*   ∞3C∞*
.END
.PT2
.FP
or occasionally (see {yon(P102)}) as:
.PT2
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.KRK
	        ⊂αααπααα⊃            ⊂αααπααα⊃
	  ααααα→~ # ~ #αβααααααααααα→~ # ~ # ~
	        %αβα∀ααα$            %αβα∀αβα$
	          ↓                    ↓   ↓
	          ∞3A∞*                    ∞3B∞*   ∞3C∞*

.BOXB
.END

.FP
This second style of graphical representation has a direct representation
in the storage layout of our machine.
Each "double-box" will be represented as a machine location and each
arrow  will be represented as a %2⊗→pointer↔←%* to a machine
location.
Notice that each box contains two pointers; therefore each corresponding 
machine location, %bloc%*,
will be interpreted as containing two machine addresses.⊗↓An actual hardware
machine may not be of sufficient word-size to accomodate two
addresses; in this case, several real words may be needed to represent
one LISP word. For example, the PDP-11 (16#bit#words) implementations typically
use two machine words (⊗↑[Har#75]↑), and micro-processor versions (8#bit#words)
may use four words (⊗↑[Pag#76]↑). In {yonss(P224)} we discuss a special
compact representation of LISP cells.←  The left-hand address
will represent the %3car%*-branch; the right-hand address 
will represent the %3cdr%*-branch:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
	        ⊂αααααπααααα⊃
	  loc   ~ car ~ cdr ~
	        %ααααα∀ααααα$
.BOXB
.END
.FP
The pointers will either reference atoms or  
point to  two-pointer boxes.
Literal atoms 
--#like %3A,#B,#C%*#-- will also be represented in machine locations, only here the
contents of each location will be an encoding of the name of the atom.
The
contents of such a location must not be interpreted as  pointers.

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	        ⊂αααααααααααααααααααααα⊃
	  loc   ~ rep. of literal atom ~
	        %αααααααααααααααααααααα$
.BOXB
.END


To help keep track of the different uses of machine locations we
will partition our machine's memory into two disjoint spaces: %2⊗→pointer space↔←%*,
which will contain two-pointer cells; and %2⊗→atom space↔←%*, which will
contain information like atoms which should not be interpreted as 
pointers.
Thus if the first box in our example were represented by location %b100%*
and the second were represented by location %b405%*, and the atoms
%3A%*, %3B%*, and %3C%* were represented by the numbers %b40%*, %b41%*, and
%b42%*, and were to be found
in locations %b710%*, %b762%*,
and %b711%*, respectively, then the following picture beginning at location
%b100%* could represent the dotted pair %3(A#.#(B#.#C))%*.

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.BOXA
.KRK

		        ⊂αααααπααααα⊃
		  100   ~ 710 ~ 405 ~
		        %ααααα∀ααααα$
.PT2
			   ...
.PT2
		        ⊂αααααπααααα⊃
		  405   ~ 762 ~ 711 ~
		        %ααααα∀ααααα$
.PT2
			   ...
.PT2
		        ⊂ααααααααααα⊃
		  710   ~        40 ~
		        εαααααααααααλ
		  711   ~        42 ~
		        %ααααααααααα$
			   ...
		        ⊂ααααααααααα⊃
		  762   ~        41 ~
		        %ααααααααααα$

.BOXB
.END
.FP
The left half of location %b100%* points to the representation of the 
atom %3A%* and the right half points to the representation of the dotted pair
%3(B#.#C)%*.
Notice too, that given the entry point into the representation --location %b100%*
in the example-- we can  discover the S-expr being represented.

This representation of S-exprs is a special case of a 
scheme called %2⊗→linked list structure↔←%*. The term  "linked" 
refers to the fact that to find succeeding elements in the representation
we must follow the explicit pointers as opposed to, say, merely
incrementing an array pointer.
The phrase "list structure"  describes an arbitrary interconnection of these
two-pointer nodes, including self-referential structures. We will discuss such
general structures later; for the moment we restrict such constructions
to LISP trees: no intersecting branches.⊗↓The  implementation of lists
using linked addresses was introduced by the IPL series of 
languages; ⊗↑[New#61]↑.← 

The particular brand of linked list structure which we have demonstrated is called
%2⊗→singly linked↔←%*.
The adjective "singly" means that only %6one%* pointer 
is stored as the representation of
the arrow, %b→%*.
This means that the representation 
only tells us how to find successor  elements in the structure. For
example, if we were looking at location %b405%* the representation
tells us how to find the %3car%* or %3cdr%*; they're at %b762%* and
%b711%* respectively. But if we wanted to find the %6predecessor%*
of %b405%* in this representation it would require some further calculation.
We would have to start at the beginning of the S-expr representation
and look for a location such that its %3car%* or %3cdr%* is the desired cell.
If a particular application required frequent discovery of such predecessors
then we might consider a more complex  representation which
would also contain information about the predecessor of each node,
essentially representing  %b→%* as %b↔%*.
.GROUP;
.P164:
For example:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.BOXA
.KRK
.TURN OFF "←"
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
	        ⊂αααπααα⊃            ⊂αααπααα⊃
	   α←→α→~ # ~ #←βααα←→αααααα→~ # ~ # ~
	        %αβα∀ααα$            %αβα∀αβα$
		  ↑		       ↑   ↑
	          ↓                    ↓   ↓
	          ∞3A∞*                    ∞3B∞*   ∞3C∞*

.BOXB
.END
.APART
.FP
One such representation is called %2⊗→doubly-linked list structure↔←%*. 
In this representation
of LISP trees we could store %6three%* pieces of information with each
 node:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
		⊂ααααααααααααα⊃
		~ predecessor ~
          loc   εααααααπααααααλ
                ~  car ~  cdr ~
	        %αααααα∀αααααα$
.BOXB
.END

.BEGIN TURN OFF "←";
Note that LISP trees always %6do%1 have
unique predecessors. In the case of list-structure, unique predecessors
do not always exist. Compromises exist in some applications: some data structures 
can be doubly-linked, allowing fast traversal but requiring more space;
while other data structures are singly linked, requiring less space, but
requiring more time to traverse (⊗↑[Gua#69]↑); still other structures may have more
compact representation as arrays or numbers.
For example, a typical representation of a vector,
or sequence of fixed length, is to store the elements sequentially
in memory.⊗↓We will discuss  these more detailed representations in {yonsec(P210)}.← 
Since each element in this structure has at most one successor
we can use the sequential addresses as implicit pointers to retrieve
successive elements. A general S-expr has two successors, thus
the  implied linear addressing scheme of most machine memories is insufficient
as it stands; LISP uses linked allocation.  Again there are compromises.
For example, the following memory representation  is valid for LISP trees:
for any location %3n%1, find its successors at locations %32n%1 and %32n+1%1;
note that the predecessor of any cell is unique.
Each location must contain an indication of whether or not it is an atom.
The remaining contents of a location is available for data; see#⊗↑[Ber#71]↑.
.END

.P140:
We will frequently  refer to several different S-exprs simultaneously;
for example, when we are talking about the implementation of the 
function %3cons%* we will be manipulating the representations of two
S-exprs. 
Similarly we will want to  refer to several pieces of a single complex
S-expr; for example we might wish to "put a finger" at a specific point
in a structure and then, depending on the result of a computation
on some sub-part, move the "finger" either left or right.
To facilitate such discussions we will assume the existence
of a set of pointer registers: %bPt%41%1, %bPt%42%1,#...,#%bPt%4n%1.
Thus, using the above example, the following represents %bPt%41%1 pointing
at %3(B#.#C)%* and %bPt%42%1 pointing at  the atom %3A%*:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.BOXA
.KRK

	   Pt∞41∞b				 Pt∞42∞b
	⊂αααααααα⊃			⊂αααααααα⊃
	~   405  ~       		~   710  ~
	%αααααααα$			%αααααααα$
.BOXB
.END	

.P159:
.FP
Implicit in our representation is the assurance that we can differentiate between
locations in atom space and locations in pointer space. For example, assume each of
our locations can hold  six digits and  assume we will
store a numeric atom as its corresponding number. Then the atom
%3762711%* would be stored as:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
		        ⊂αααααααα⊃
		        ~ 762711 ~
		        %αααααααα$
.BOXB
.END	
.FP
Since this is exactly the contents of location %b405%*⊗↓The vertical
bar doesn't appear in  the machine's memory.← some confusion
is possible: is the contents a number or is it two pointers? 
A typical trick is to partition memory such that  particular portions of the
address space correspond to each of the logical spaces:
atom space or pointer space. In our example we could assume that addresses
less than %b700%* are locations for pointers, while addresses  
greater than  or equal to %b700%*
 contain atoms. Thus the representation of %3762711%* would
appear in a location with address %b700%* or greater.

Though our memory system is not completed yet, we %6do%* have enough
structure to begin a discussion  of the implementation of some of the
primitive LISP operations.

.CENT(Problems)
.nl
1.##What problems do you foresee in using the double-linking scheme for
representing LISP's S-exprs?
.end "sexpr"
.SS(Representation of LISP Primitives,,P26:)
.begin "rep"
.SELECT 1;
.FP
Now that we have some of the representational problems for S-exprs
reasonably well in hand we will look at the implementation of the
LISP primitives. We will  examine %3car, cdr, eq,%* and %3atom%*
in this section, leaving %3cons%* for later.

We must understand how these primitives  obtain their parameters and
how they are to return their values.
Recall our discussion of environments and destinations in {yonss(P209)}.
An environment chain was constructed 
by linking destination blocks whose value slots have been filled. 
A dest-block was
created when we recognized a function application.⊗↓If
the application supplied an incorrect number of arguments no dest-block is built;
the debugging routine is called. Several  implementations supply
missing arguments with %3NIL%1 or evaluate and discard extra arguments.
This treatment of improper calling sequences ignores one of the most 
common sources of bugs in LISP programs (⊗↑[Mot#76]↑).← 
The name components of a  block are either the λ-variables in the case of
a λ-application or are system-generated names in the case of primitive application;
the value-slots of a dest-block
received the evaluated actual parameters.
When a dest-block
was filled, it was chained onto the front of the environment and we were ready
to call the function. Thus
the first block on the environment chain was the local symbol table.
The function was expected to return its
value to a designated dest-block, and then return to the interrupted computation.
So, on entrance to a primitive we have access to at least two structures:
a destination block and the environment chain.

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
    ∞3dest∞*	     	       ∞3env∞*
    ~			   ~
    ~	⊂ααααααα⊃	   ~	⊂ααααααα⊃
    %α→ ~     #αβα⊃ 	   %αα→ ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #    		  # # #
	~   ~   ~←$		~   ~   ~
	εαααβαααλ  		εαααβαααλ  
        ~   ~   ~		~   ~   ~
          # # #		        %ααα∀ααα$
       	εαααβαααλ  		       	
        ~   ~   ~		        
       	%ααα∀ααα$  		  
.BOXB
.END
.FP
.BEGIN GROUP;
Here is how %3car%* uses these structures:

.BEGIN INDENT 10,10;
Let %3val%1 be  the value-part of the first entry in the local table. 
If %3val%1 is an atom then %3car%* is undefined; the implementation
should send a message to the debugging package (see {yonss(P168)}).
If %3val%1 is %6not%* atomic,  it has a left- and  right-hand side.
We should send the %6left%*-hand side of %3val%1 to the value part of the
slot pointed to in the dest-block.
.END
.END

.GROUP;
.FP
For example:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
    ∞3dest∞*	     		∞3env∞*
    ~			    ~
    ~	⊂ααααααα⊃	    ~	⊂ααααααα⊃
    %→  ~     #αβα⊃ 	    %→  ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~102~
	~   ~   ~←$		%ααα∀ααα$
	εαααβαααλ  	        
	~   ~   ~	
	  # # #
	εαααβαααλ		⊂αααπααα⊃
        ~   ~   ~	 102    ~204~ 22~
       	%ααα∀ααα$ 		%ααα∀ααα$
.BEGIN CENTER;SELECT 2;
Before
.END
.BOXA
	⊂ααααααα⊃		⊂ααααααα⊃
        ~     #αβα⊃ 		~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~102~
	~   ~204~←$		%ααα∀ααα$
	εαααβαααλ 
        ~   ~   ~	
          # # #		
       	εαααβαααλ 	  	⊂αααπααα⊃
        ~   ~   ~	 102    ~204~ 22~
       	%ααα∀ααα$ 		%ααα∀ααα$
.END
.BEGIN CENTER;SELECT 2;
After
.END

.LE(6,Example for %3car%1)
.BOXB
.APART
.FP
For successful completion %b%3car%1 expects  that its actual parameter
represents
 a node in pointer space; otherwise we get an error. If the operation
is successful then the dest-slot is changed to point to whatever was pointed to
by the left-hand side of the selected cell.
The description of %3cdr%* is sufficiently similar that we leave it to the
reader. 

.GROUP;
On {yon(P159)} we described the internal structure of LISP atoms. Using that
representation we can give a simple implementation for the predicate %3atom%*:
.BEGIN INDENT 10,10;
Does the actual parameter point into that area reserved for atom names? 
If so, send 
a representation of truth as value, otherwise send a representation of
false.
.END

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
   ∞3dest∞*	     	        ∞3env∞*
    ~			   ~
    ~	⊂ααααααα⊃	   ~	⊂ααααααα⊃
    %→  ~     #αβα⊃ 	   %→   ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~710~
	~   ~   ~←$		%ααα∀ααα$
	εαααβαααλ 		⊂ααααααα⊃
        ~   ~   ~	 710	~    "A"~
          # # #		        %ααααααα$   
       	εαααβαααλ 	  	⊂ααααααα⊃
        ~   ~   ~	 714    ~    "T"~
       	%ααα∀ααα$ 	        %ααααααα$
.BEGIN FILL
∞1We are writing ∞b"A"∞1 instead of the numeric encoding. Thus ∞b"A"∞1 is really ∞b40∞1.∞b
.END
.BEGIN CENTER;SELECT 2;
Before
.END
.BOXA
	⊂ααααααα⊃		⊂ααααααα⊃
        ~     #αβα⊃ 	        ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~710~
	~   ~714~←$		%ααα∀ααα$
	εαααβαααλ  		
        ~   ~   ~	
          # # #		
       	εαααβαααλ 
        ~   ~   ~	
       	%ααα∀ααα$ 	
.END
.BEGIN CENTER;SELECT 2;
After
.END
.LE(6,Example for %3atom%1)
.BOXB
.APART
.FP
Notice that we did not need to examine the contents of location %b710%*, 
thus saving one storage reference.
It was sufficient to know that the location was between predetermined bounds.
If the actual parameter was not pointing at an atom we would have returned a pointer to
a location containing %b"NIL"%1.

.GROUP
Finally we describe an implementation of %3eq%*:
.BEGIN INDENT 10,10;
Do both actual parameters point into atom space?
If not the result is undefined. If they %6do%*  then do they reference the same atom?
We can determine this latter condition in two ways: first, they
might point to two different locations in atom space; we would have to examine the
contents of those locations; if they agreed then %3eq%* should return  a 
representation of truth. A more satisfactory solution is to store 
each atom %6uniquely%*; one location will be reserved for %b"A"%1, etc. Now
all %3eq%* need do is make sure that both slots point
into atom space %6and%* point to the same location. Thus no additional 
memory reference is required. From now on we will require that all atoms are
 stored uniquely.
.END

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK;BOXA
   ∞3dest∞*	     	       ∞3env∞*
    ~			   ~
    ~	⊂ααααααα⊃	   ~	⊂ααααααα⊃
    %→  ~     #αβα⊃ 	   %→   ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~710~
	~   ~   ~←$		εαααβαααλ
	εαααβαααλ  		~   ~710~  
        ~   ~   ~	        %ααα∀ααα$
          # # #		        ⊂ααααααα⊃
       	εαααβαααλ 	 714    ~    "T"~
        ~   ~   ~	        %ααααααα$
       	%ααα∀ααα$ 	        ⊂ααααααα⊃
			 710    ~    "A"~
                 	        %ααααααα$
.BEGIN CENTER;SELECT 2;
Before
.END
.BOXA
	⊂ααααααα⊃		⊂ααααααα⊃
        ~     #αβα⊃ 	        ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~710~
	~   ~714~←$		εαααβαααλ
	εαααβαααλ  		~   ~710~  
        ~   ~   ~	        %ααα∀ααα$
          # # #		        ⊂ααααααα⊃
       	εαααβαααλ 	 714    ~    "T"~
        ~   ~   ~	        %ααααααα$
       	%ααα∀ααα$ 	        ⊂ααααααα⊃
			 710    ~    "A"~
                 	        %ααααααα$
.END
.BEGIN CENTER;SELECT 2;
After
.END
.LE(6,Example for %3eq%1)
.APART


We still have a ambiguity to resolve if we  represent
the number
%340%1 as %b40%1 and represent
 the atom %3A%1 as %b40%1. {Yonss(P128)} resolves this conflict.
.end "rep"
.SS(AMBIT/G,,P275:)
.begin "amb"
.P158:
.FP
Before  investigating the implementation of atoms,
we should explore other  possible descriptions for LISP's primitives.
We have described the primitives by example;
it would be more
pleasing if we could describe each primitive in more general terms.
Fortunately we can,
using a micro-version of a graphical language called ⊗→AMBIT/G↔←.⊗↓AMBIT/G
is an acronym
for Algebraic Manipulation By Identity Transformation/Graphical.← 

When   developing a complex structure-manipulating
program,  we draw  pictures. In LISP we frequently describe data
structures  graphically and in the previous
 section we  gave  graphical descriptions
of the LISP primitives using examples. AMBIT is an extension of
both of these ideas; it
is a graphical language for the description of both
data and algorithms. 

The basic statements of the language are %2pattern-match%1 and %2replacement%1 
rules.  
Several programming languages have complex pattern matchers; AMBIT's
uniqueness is its graphical presentation of the patterns.
Patterns are described  as combinations of shapes and solid arrows.
If an instance of a pattern can be
found in the current state of the computation, then we will replace 
that instance with a new pattern.  
The only kind of replacement we will allow is the %2swinging%*
of an arrow so that its head moves from one node to another; the
tail of the arrow is immovable.
Thus the new pattern differs from the old only in the positioning
of some of the arrow heads.
Where the arrow head strikes a node is immaterial.
Dashed arrows show replacements to be made if the pattern matches.
Portions
of the shapes marked with "?" are "don't-care" conditions.
.GROUP;
For example, here's %3car%*:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
    ∞3dest∞*	     		∞3env∞*
    ~			   ~
    ~	⊂ααααααα⊃	   ~	⊂ααααααα⊃
    %→  ~     #αβα⊃ 	   %→   ~     #αβαα ### →
	εαααπαααλ ↓		εαααπαααλ 
          # # #			~   ~ # ~
	~   ~   ~←$		%ααα∀αβα$
	~   ~ # → - → ⊃	      	      ~
	εαααβαααλ     ↓		      ↓
        ~   ~   ~   		⊂αααπααα⊃
          # # #	      |		~ # ~ ? ~
       	εαααβαααλ     	  	%αβα∀ααα$
        ~   ~   ~     ↓	          ↓
       	%ααα∀ααα$ 	   	⊂ααααααα⊃
		      %→ - → - →~   ?   ~
				%ααααααα$
.END
.LE(6,Algorithm for %3car%1)
.APART
.FP
This AMBIT diagram contains equivalent information to the previous
%6example%* of %3car%*, but the extraneous details of specific
addresses  have been stripped away.
We will use such diagrams occasionally when they will contribute to clarity.
.CENT(Problem)
Give an AMBIT diagram for %3eq%1.
.end "amb"
.SS(A Few Programming Techniques,,P214:)
.BEGIN "TRICKS"
.FP
There are a few useful and practical LISP programming techniques
which take advantage of the implementation.
These tricks are supported in most implementations and are useful
enough that they should be documented as programming language features.

.BEGIN NL;GROUP;
%21.%1 In most implementations of %3eq%1
the check for atom-ness is suppressed and a simple address comparison
is made. Non-atomic S-expressions are not usually stored uniquely;⊗↓See
the problem on hash consing on {yon(P154)}.←  Thus
in most implementations
.BEGIN tabit1(10);
.boxa
\%3eq[(A . B);(A . B)]%*      is usually false, but
.PT2
\%3eq[x;x]       %*is usually true for any %3x%*.
.END
.FP
.boxb
We are %6not%* changing the definition of %3eq%*; 
it is still undefined for non-atomic arguments.
The preceding remarks deal only with the usual implementation of 
%3eq%*.⊗↓Formally, the implementation %6is%1 wrong in not satisfying
the definition. Pragmatically, the implementation is convenient.←
.END

.NL
%22.%1 The implementation of the truth values %et%1 and %ef%1 is
usually simplified, mapping %ef%1 onto %3NIL%1, but allowing
anything %6but%1 %3NIL%1 as a representation of %et%1.
This allows several related tricks:
.BEGIN tabit1(10);
.PT2
\%2a.%1 Any expression may be used as a predicate, and
.PT2
\%2b.%1 Used as a predicate, %3not[null[l]]%1 has the same effect as %3l%1.
.PT24
.END
.APART;
.GROUP;
.FP
For example, consider the following extended version of the predicate 
%3member%1.

.BEGIN SELECT 3;TABIT1(18)
.BOXA
mem%9'%3 <= λ[[x;l]\[null[l] → %ef%3;
\ equal[x;first[l]] → l;
\ %et%3 → mem%9'%3[x;rest[l]]] ]
.END
.BOXB
This "predicate", %3mem%9'%1,  will return %ef%1 if no matching element is 
found, otherwise
it will return the list beginning at the match. The  non-empty list can be used
as an indication of truth, and can also supply the calling function with the
match if  a match  is found.
.APART;
.GROUP;
.NL
%23.%1 Several implementations of conditional expressions allow
"p%4i%1" as an abbreviation for "p%4i%1#→#p%4i%1". The computational effect is
the same, but p%4i%1 is only evaluated once.
.GROUP;
Using this feature, %3mem%9'%1 could be written:
.BEGIN SELECT 3;TABIT1(18);
.BOXA
mem%9'%3 <= λ[[x;l]\[null[l] → %ef%3;
\ equal[x;first[l]] → l;
\ mem%9'%3[x;rest[l]]] ]
.BOXB
.END
.APART
.FP
This 
feature is more useful in contexts where we wish to test for the existence
of an object and, if a match is found, do something with the object.
For example, the trick of {yon(P219)} could be written:
.BEGIN tabit1(20);SELECT 3;TURN OFF "←";
.BOXA
\\[cont ← isspec[fun;spectbl];
\\ isprim[] → ...; ...]
.PT2
%1where:%3
.END
.BEGIN tabit2(4,22);SELECT 3;TURN OFF "←";GROUP;
.PT2
\isspec <= λ[[x;l]\[null[l] → ( );
\\ eq[name[first[l]];x] → value[first[l]];
\\ isspec[x;rest[l]]]]
.SELECT 1;
.boxb
.FILL;
Since
the result of %3value%1 will be a function name, and never %ef%1,
there will be no ambiguity in using  %3isspec%1 as a predicate.
.END

.CENT(Problem)
.NL
1.##The application of these  tricks may give rise to 
some unaesthetic programs. Typically we have to test for existence then,
assuming an instance was discovered, we have to perform further computation
on that instance.⊗↓If no further computation is necessary, trick No.#%23%1 
suffices.←  Constructs like:
.BEGIN CENTER;SELECT 3; turn off "←";
.boxa
[it ← test[object] → smash[it]; ...]
.boxb
.END
.BEGIN INDENT 4,4;
arise. The objectional aspect involves the variable %3it%1. The variable %3it%1 is not local
to the conditional expression. Either %3it%1 is global: an unnecessarily
gratuitious side-effect; or %3it%1 is bound by  an enclosing
λ-expression or a %3prog%1.
In either case the binding is too far removed from its usage. Sussman and Steele
⊗↑[Sus#76]↑ suggest the construct:
.END
.BEGIN CENTER;
.boxa
%3test[<form%41%1>; %3λ[[x] %1<form%42%1>]; <form%43%1>] 
.boxb
.END
.BEGIN INDENT 4,4;
with the following semantics: evaluate <form%41%1>; if it gives 
a value other than %ef%1 then
apply the second argument, a unary function, to that value. Otherwise
evaluate <form%43%1>.
.pt2
.begin indent 4,4;
Recast the %3isspec%1-argument of {yon(P219)} in terms of %3test%1.
Give an implementation of %3test%1 by extending one of our evaluators.
.end
.END
.END "TRICKS"
.SS(Symbol Tables and Property-lists,,P128:)
.begin "st"
.FP
Since we are examining  implementation details,
and since manipulation of symbol tables is such a central issue
in evaluation, we should also scrutinize symbol tables
and their organization.
We have seen two fundamentally different  symbol 
table organizations: deep binding and shallow binding. 
We should examine the implications
 of these organizations, and probe deeper into 
their implementation.
If the number of entries associated with an atom is small then shallow binding
may be advantageous.
If the number of entries associated with an atom is very large then
the shallow binding technique may be too costly and deep binding or yet
another  organization may be required (⊗↑[McD#75]↑).

.P139:
Recall our discussion of %3getval%1,    %3addval%1, and %3getval_cell%1 
in {yonss(P134)}.
These functions were developed to describe shallow binding, but
they are illustrative of a more general idea. In symbol manipulation
and symbolic programming, we often want to be able to associate a set
of data with an item. For example, an algebraic simplifier
would like to know whether  a specific operator is commutative; if so,
certain simplifications are valid. We could maintain a list of all commutative
operations and require that the simplifier check that list. But since
commutativity is a property of the operator it seems more natural to
associate the property with that operation. Search considerations also
arise if the list of operations is long.

We generalize the idea expressed in %3getval%1 and %3addval%1,
allowing the association of an arbitrary collection of 
%2property-value%* pairs with an atom.
With each atom we will
associate a list called the %2⊗→property-list↔←%* or 
%2p-list%*.⊗↓Property lists were introduced  to programming languages
in the IPL series of languages#⊗↑[New#61]↑.← 
The names, %2attribute%1 or %2indicator%1, are sometimes used as synonyms
for property. An atom is frequently called a %2carrier%1 of the properties.

A property list is a table of properties and property#values. The size of the
property list is not fixed, but can shrink and grow during a 
computation.

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK;BOXA
	     	⊂αααααααπααααα⊃
	        ~ prop1 ~ val1~
		εαααααααβαααααλ
	        ~ prop2 ~ val2~
	             # # #
		εαααααααβαααααλ
	        ~ propn ~ valn~
	       	%ααααααα∀ααααα$  		  
.BOXB
.END
.FP
We have seen an identical diagram in {yonss(P220)}; property lists
are a very effective tool for modelling data bases.⊗↓They
are by no means the %6only%1 or %6best%1 way of representing
a data base. See ⊗↑[McD#75]↑.← 
Thought of
as abstractions, property lists are symbol tables. The name-entries
are properties and the value entries are  the property values.

.GROUP;
We identify an atom with its property list.  
For example,
if we wished to represent the "+"-operation as the atom %3PLUS%1
and wished to signify that the operation is commutative and binary,
the atom %3PLUS%1 might be represented as:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK;BOXA
	PLUS 	⊂αααααααπααα⊃
	        ~ commu ~ T ~
		εαααααααβαααλ
	        ~ arity ~ 2 ~
	       	%ααααααα∀ααα$  		  
.END
.BOXB
.APART
.FP
In these kinds of applications, we are using the
atom  as a data structure and attaching properties to that atom
rather than thinking of the atom as a representation of an identifier.
.GROUP;
.FP
For example:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	CAR 	⊂αααααααπααααααα⊃
	        ~ MFGR  ~ BUICK ~
		εαααααααβαααααααλ
	        ~ YEAR  ~  1959 ~
	       	%ααααααα∀ααααααα$  		  
.END
.BOXB
.APART
.GROUP;
.FP
These same techniques are
applicable when we consider atoms as representations of variables as
used in  the evaluation process. 
In fact, an atom can  simultaneously be used as a carrier of a value and
can also have a property list:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	    E4
	    ⊂αααπααα⊃
	  ⊂←β X ~ 3 ~
	  ↓ εαααβαααλ
	      # # #      E3
	  ↓ %ααα∀ααα∀→αα→⊂αααπααα⊃
	  ~		   # # #  
	  ↓		 εαααβαααλ
	  %→ααα→π←αα←ααα←β X ~ A ~     E1
	        ↓      ↑ %ααα∀ααα∀→ααα→⊂αααπααα⊃
	⊂αααααααπααααα⊃~ 	     	 # # #
	~ prop1 ~ val1~~	       εαααβαααλ
	      # # #    %←ααααα←ααααα←ααβ X ~ B ~
	εαααααααβαααααλ		       εαααβαααλ
	~ propn ~ valn~		         # # #
	%ααααααα∀ααααα$  	       %ααα∀ααα$
	  ∞1p-list for ∞3X∞1
.BOXB
.END
.APART;
.next page
.GROUP;
.FP
All instances of %3X%1 share a common property list, but
the value, or binding of %3x%1 is found  using the environment chain.
This example is described in terms of deep binding, but the
property-list idea is also directly applicable to the shallow binding schemes.
To adapt p-lists to the first shallow binding scheme
of {yon(P217)}, we introduce a property named %3VAR%1
whose property value will be the collection of environment-value pairs:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	X ⊂αααααααπαααααα⊃     ⊂ααααπααα⊃
	  ~  VAR  ~    #αβα→αα→~ E4 ~ 3 ~
	  εαααααααβααααααλ     εααααβαααλ
	  ~ prop1 ~ val1 ~     ~ E3 ~ A ~
	  εαααααααβααααααλ     εααααβαααλ
	      #   #   #        ~ E1 ~ B ~
	  εαααααααβααααααλ     %αααα∀ααα$
	  ~ propn ~ valn ~
	  %ααααααα∀αααααα$
.BOXB
.END
.FP
Similarly, the second shallow binder could use:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	X ⊂αααααααπαααααα⊃     
	  ~ VALUE ~    #αβα→∞1<current value>∞*
	  %ααααααα∀αααααα$     
.BOXB
.END


.APART
In summary, property lists are a 
language feature which is independent of the binding strategy
we have implemented. A property list can contain  all the aspects of an atom
which we wish to consider; the class of attributes need not be fixed, but can
vary during the execution of the program. 
Those properties need not involve the fact that atoms are
used to represent identifiers when we map the
meta#language onto data structures. 
The deep binding implementation emphasizes that
the value of a variable  is associated with the environment in which that
value is created. However a shallow binding organization associates values
with variables, and thus it is natural to think of property-lists when
thinking of shallow binding.

We wish to look more closely at the value aspects of atoms.
We have seen three properties related
to the value of a variable: simple value, call-by-value function (expr) and
call-unevaluated function (fexpr). We were able to distinguish between exprs and
fexprs: either place the fexpr name in a special list;
or store the fexpr as a β-expression, rather than as a λ-expression.
We made no explicit distinction between simple values and  function values;
if a simple value appeared in the function position of an application, we
evaluated that expression until we %6did%1 discover a function object.⊗↓It may
be a bad idea to distinguish between the evaluation of an argument position and the
evaluation of a function position.←
If a function appeared in a position expecting a simple value, then the
data structure interpretation of the function object was taken.
.next page

Since "<=" and "<%4f%1=" were defined to place the appropriate function definition
in the global table, we can interpret  these operations as associating the
definition with the atom. That is, being an expr or fexpr is  a property of the
atom. Similarly, globally bound variables like %3t%1 and %3nil%1 play the roles of
constants and therefore can be interpreted as having a value associated with
them. Primitive functions like %3car%1, and primitive special forms like
%3cond%1 should also be considered  constants. Their "values"
are fixed procedures for specific call-by-value and call-unevaluated operations,
respectively.⊗↓Many implementations are less restrictive: %21.%1 %3T%1 and
%3NIL%1 can be redefined; %22.%1 %3car%1, %3cdr%1 and the other primitives can be
redefined. Allowing %21%1 will always lead to grief. %22%1 is justified
only for debugging calls on these functions; however, if one programs
abstractly, there will be no need to  debug such low level calls.←
.apart
.GROUP;
This discussion exemplifies five value-like properties which are properties
of an atom, rather than properties of a particular environment:⊗↓We will
discuss the  %3VAR%1  and %3VALUE%1 properties later.
  That will be the intent of
{yonss(P225)}.← 

.BEGIN TABIT2(5,30);GROUP;
.BOXA
\%3CONST%1\simple value; used as a constant
\%3EXPR%1\call-by value definition
\%3FEXPR%1\call-unevaluated definition
\%3SUBR%1\call-by-value primitive
\%3FSUBR%1\call-unevaluated primitive
.END
.BOXB
.APART
In {yonss(P57)}
we will introduce another  protocol for assigning values
to variables, but at any one time an atom may have at most one
of these value-related indicators.⊗↓Several 
implementations allow atoms to have several of these system properties.
Thus  expressions like %3car[car]%* are executable.
The implementation uses context to determine which %3car%1 is a simple variable
and which %3car%1 is the primitive procedure. 
The current %3eval%* %6will%* operate correctly on this example since
a recognizer for the function %3car%* is explicitly encoded in %3apply%*, 
but such tricks lead to unnecessarily
mysterious programs. 
 For 
the same reason, the LISP obscenity %3λ[[lambda]#...#]%* will work.
Notice its S-expr representation is %3(LAMBDA#(LAMBDA)# ...#)%*.
Context is used by an evaluator in  slightly 
less obnoxious ways. For example,
an evaluator for %3prog%* can
tell a reference to the label %3x%* from the %3prog%*-variable %3x%* in
%3#...#prog[[x;y]#...#x#f[..]#...#g[x#...#]#...#go[x].%* See {yon(P83)}.← 


.GROUP;
.FP
For example, %3car%1 might be represented as:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.TURN ON "?" FOR "\";
.KRK;BOXA
     	⊂ααααααπααα⊃
        ~ SUBR ~ #αβ→∞1To machine language code for ∞3car∞b
       	%αααααα∀ααα$  		  

.END
.LE(6,Part of the atom-structure for %3CAR%1)
.apart
.BOXB
.FP
When %3apply%1 recognizes %3CAR%1 as a representation for the function
%3car%1,
the machine-dependent code will be executed, but %3CAR%1 can also be used
  as an atomic data structure.
For example:
.boxa
.begin centerit 
in  %3eval[(CAR (QUOTE (CAR BMW)));( )]%1 both uses of %3CAR%1 will appear.
.end
.boxb
.BEGIN CENTERIT;GROUP;
.P29:
.KRK
As a further example, consider the representation of:
.PT2
←%3fact <= λ[[x][x=0 → 1; %et%* → times[x;fact[sub1[x]]]]]
.PT2
%1The right-hand side would be:
.PT2
.SELECT 3;TABIT3(5,32,46);
\(LAMBDA (X) (COND\((ZEROP X) 1) 
\\(T (TIMES\X 
\\\(FACT (SUB1 X))))))
.END
.BOXB
.FP
To represent the intention that %3fact%* is to be defined as
the above recursive function, we might store the S-expr representation
on the property-list of the atom %3FACT%* and use %3EXPR%*
as its indicator. The occurrence of the atom %3FACT%1 in the λ-expression
is represented as a pointer to the atomic  structure of %bFACT%1.
.GROUP
.FP
Here is  part of the atom-structure for %3FACT%*:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
      ⊂ααααααπαααα⊃ 
FACT  ~ EXPR ~  #αβ→⊃
  ⊂αα→%αααααα∀αααα$ ~
  ↑  ⊂←αααα←ααααα←αα$
  ~  %→⊂ααααααααπααα⊃   ⊂αααπααα⊃  ⊂αααπαα⊃  
  ~    ~ LAMBDA ~ #αβαα→~ # ~ #αβα→~ # ~≤'~
  ~    %αααααααα∀ααα$   %αβα∀ααα$  %αβα∀αα$ 
  ↑		          ~	     ↓
  ~	       ⊂αααααααααα$   ⊂ααααααπααα⊃ 
  ~	       ↓	      ~ COND ~ # ~ 
  ~	    ⊂αααπαα⊃	      %αααααα∀αβα$ 
  ↑	    ~ X ~≤'~   		       ↓
  ~	    %ααα∀αα$   	      ⊂αααπααα⊃ ⊂αααπαα⊃
  ~			      ~ # ~ #αβ→~ # ~≤'~
  ~			      %αβα∀ααα$ %αβα∀αα$
  ↑		  		↓         ↓
 . . .                        . . .     . . .
  ~					  ↓
  ~				      ⊂αααπααα⊃ ⊂αααπαα⊃
  ↑				      ~ # ~ #αβ→~ # ~≤'~
  ~				      %αβα∀ααα$ %αβα∀αα$
  %←αααα←αααααα←ααααα←ααααα←ααααα←ααααα←$         ↓
				     ⊂←αααααα←αααα$
				     ↓
				  ⊂ααααααπααα⊃ ⊂αααπαα⊃
				  ~ SUB1 ~ #αβ→~ X ~≤'~
				  %αααααα∀ααα$ %ααα∀αα$
.END
.LE(6,Atom-structure for %3FACT%1)
.APART
.BOXB
.FP
Every occurrence of an atom --%bEXPR%1, %bLAMBDA%1, and so forth--
is actually a reference to the appropriate atomic structure.
Note that both instances of %bX%1 are actually pointers to the representation
of %3X%1, but that two  representations of %3(X)%1 will typically be 
distinct.
Also keep in mind that we are storing the data structure
%6representation%1 of the %3fact%* function.
.BEGIN indent 10,10,10;
.BOXA
%3(LAMBDA#(X)#(COND#((ZEROP#X)#1) ##(T##(TIMES##X##(FACT##(SUB1##X)))))#)
.BOXB
.END
.FP
is a perfectly good list.  If we attached it
to the indicator %3VALUE%* then we would have represented the list as the 
%6simple%* value of %3fact%*.

Representations of special forms like %3COND%* and %3QUOTE%* give rise to the
indicator  %3FSUBR%*.
When an instance of such a special form is
recognized, the argument list is passed to the primitive without
any evaluation.
In a similar manner we introduce the indicator %3FEXPR%1 to designate  
the occurrence of a "<%4f%1=" definition. 

Our discussion of property lists as carriers of values has centered
on the representations of constants; many identifiers in LISP
are constants. Even though we can redefine functions using 
a version of "<=", most such definitions are relatively constant.⊗↓To
define a temporary function we use %3label%1.←  The primitive functions
are also constant. Shallow binding tries to capitalize on this
observation, by associating all of the value aspects of a variable
with the property list, and we will soon see that for several interesting
subsets of LISP, we can significantly simplify the handling of shallow binding.
Before discussing that, we will 
show how an evaluator might use such property-list information. This
requires  the introduction of property-list manipulating functions.
.end "st"
.SS(Property-list Functions)
.BEGIN "PLFUNC"
.BEGIN GROUP
.FP
.P142:
There are four functions for manipulating  the property-list:
.p52:
.BOXA
.def
%3putprop[a;v;p]%1  
 will put the value %3v%* under the property %3p%* on the 
property-list
of the atom %3a%*. If the property %3p%* already appears on the p-list then the
%3v%* over-writes the old value; otherwise a new property-value pair is added
to the front of the p-list of %3a%*. The value returned by %3putprop%* is 
%3v%*.⊗↓In some implementations, the old pair is removed and the new pair
is added to the front of the p-list. The idea is that  since short
p-lists are usually searched linearly, one should have the most
popular properties near the front of  the list. This reorganization of
the table can even be extended to include %6references%1 to properties, always moving
the last referenced property pair  to the front of the list ⊗↑[Riv#76]↑.← 
.END
.BEGIN def;GROUP
%3get[x;i]%1 
 will search the property-list of the atom %3x%* looking for the
indicator %3i%*. If %3i%* is found the value associated with that indicator is
returned by %3get%*.
If %3x%* does not have the
indicator then %ef%* is returned.
Thus %3getval[x]%1 could be defined as %3get[x;VAR].
.END

.BEGIN def;GROUP
%3getl[x;l]%1 
will search the property-list of the atom %3x%* for the %6first%* occurrence
of any indicator which appears in  the list, %3l%1, of indicators.
   If such a match 
is found, then the %6remainder%* of the p-list, beginning with the
matching indicator, is returned.  If no match is found, %ef%* is
returned.
The virtue of %3getl%* is that it can distinguish between an atom which has 
an indicator with value %ef%* and an atom which does not have the indicator.
%3get%* cannot communicate this distinction.
The disadvantage of %3getl%1 is that it gives access to the internal structure
of the p-list,
and therefore access to the representation  of the atom. 
Such p-list functions are useful
but dangerous (⊗↑[Sam#75]↑).
.END
.BEGIN def;group;
%3remprop[n;p]%1: The final function in this class is used to remove 
property-value pairs
from the p-list of an atom. The function is named ⊗→%3remprop%*↔←.
 %3remprop%*
has two arguments: %3n%*, an atom; and %3p%*, a property. If the property 
is found on the
p-list of the atom, then %3remprop%* removes the property-value pair and returns
%et%*; otherwise it returns %ef%*.
.END
.BOXB
.END "PLFUNC"
.SS(An %3eval%* for Property-lists,,P237:)
.BEGIN "PLEVAL"
.FP
The evaluators in this section  do not reflect typical implementation
policies, but
illustrate the use of property lists and introduce  the first
non-trivial application of LISP's ability to interchange program with data.
Though this chapter is mostly concerned with the %6static%1 organization of 
LISP, the ideas involved in the evaluator are sufficiently important and
demonstrative of the power of property lists that we include them here
rather than later.

The first evaluator uses property names like %3CONST%1 and %3EXPR%1 as 
representations for functions %3const%1 and %3expr%1.
Discovering that an atom has the %3CONST%1 property, the evaluator %6applies%1
the function named %3const%1 to perform the evaluation. In this case, 
the evaluation is simple: return the represented constant. 
We will assume a shallow binding implementation and therefore
variables are handled by recognizing the property %3VAR%1 and
passing the evaluation to  the function %3var%1. In the case of an 
application, we have more work to do; %3expr%1 handles that.
The actual application, is handled  using LISP's computed function
facility discussed on {yon(P227)}.

We will describe a sequence of evaluators based on property list manipulation.
We will not express all of the details of this family of evaluators, but
leave many of the details to the reader.

.BEGIN SELECT 3;GROUP;NOFILL;TURN ON "\";KRK;TABS 13,45,51,52;
.BOXA
eval  <= λ[\[exp;env]
\[atom[exp] → form_name[getl[\exp;
\\(VAR CONST)]] [exp;env];
\ atom[first[exp]] → form_name[getl[\first[exp];
\\\(\EXPR
\\\\FEXPR)]] [exp;env];
\ ... ]]
.PT2
.END
.BEGIN SELECT 3;GROUP;TABIT3(24,37,45);
.PT2
var <= λ[[form;env] lookup[form;env]]
.PT2
const <= λ[[form;env] denote[form;env]]
.PT2
expr <= λ[[form;env]\λ[[def] eval[\body[def];
\\mkenv[\vars[def];
\\\evlist[args[form];env]] ]
\###[get[func[form];EXPR]]]
.BOXB
.END
.FP
No substantial benefit is apparent after all this work.
With a slight change, we could extract a small improvement: replace
the explicit lists %3(VAR#CONST)%1  and %3(EXPR#FEXPR)%1 with
%3idprop%1 and %3appprop%1. Bind these variables globally to the
respective lists. Then if we wished to define a new kind of calling
sequence, say %3gexpr%1s, we could add %3GEXPR%1 to %3appprop%1 and 
write a function named %3gexpr%1 to handle the evaluation
of %3gexpr%1 forms. However with further analysis, we can do much better.

Consider  simple variables. Each instance of a simple variable has the
same value property; when we see %3x%1 we apply %3lookup%1 through %3var%1;
when we see %3y%1 we apply %3lookup%1 through %3var%1. However
the association of a value property with each %6instance%1 of a variable
is discomforting. The value property is more a property of the class of variables
than it is a property of an instance.
That is,
an instance inherits a property by being a member of a certain class.


Let the atom %3VAR%1 represent the class of variables; let the atom
%3EVAL%1 represent the property name describing value properties.
The function %3lookup%1 is therefore a property value of the atom
%3VAR%1, and should be associated with the property name %3EVAL%1.

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
X ⊂αααααααπαααααα⊃     ⊂ααααπααα⊃   VAR	⊂ααααααπαααααααα⊃
  ~  VAR  ~    #αβα→αα→~ E4 ~ 3 ~	~ EVAL ~ LOOKUP ~
  εαααααααβααααααλ     εααααβαααλ	%αααααα∀αααααααα$
  ~ prop1 ~ val1 ~     ~ E3 ~ A ~
  εαααααααβααααααλ     εααααβαααλ
      #   #   #        ~ E1 ~ B ~
  εαααααααβααααααλ     %αααα∀ααα$
  ~ propn ~ valn ~
  %ααααααα∀αααααα$
.BOXB
.END
.FP
Now the evaluator should do a double %3get%1, looking down the property list of
an object, for a class name which has an %3EVAL%1 property.
Finding %3EVAL%1, the evaluator applies the associated property value to the
object and the environment. 


Before presenting the next evaluator we should settle one more point.
In the preceeding %3eval%1 we ignored the question of anonymous λ-expressions;
we assumed that the function-part of an application was an atom. We
did this becaue we have implied that only atoms have property lists. We will
remove this restriction for the next evaluator and assume that any object 
can have a property list. A λ-expression will have a property list with
(at least) property name %3LAMBDA%1 and property value of the repesentation
of the λ-expression. The atom %3LAMBDA%1 will have an %3EVAL%1 property
whose value is the function %3eval_λ%1; this function will evaluate
applications whose function-parts are  λ-expressions. 

Finally, since %3eval_λ%1 handles most of the evaluation of an application,
there is no need to make %3expr%1 do it too. In fact, our previous distinction
between %3VAR%1 and %3EXPR%1 is unnecessarily restrictive. We should
be able to return functions as values just as we can return constants
or simple values.
So %3EXPR%1 should be a property name, with property value being
the λ-expression, but %3EXPR%1 should now have  an %3EVAL%1 property
which is just %3lookup%1.
.GROUP
.FP
For example:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
plist for FACT    plist for (LAMBDA (X) 
				    ((ZEROP X) ... )))
⊂ααααααπααα⊃    ⊂ααααααααπααα⊃
~ EXPR ~ #αβ→αα→~ LAMBDA ~ #αβ→αα→ (LAMBDA 
εααααααβαααλ    εααααααααβαααλ      (X) 
     # # #             # # #         (COND ((ZEROP X)
%αααααα∀ααα$    %αααααααα∀ααα$       ... )))


 plist for EXPR      plist for LAMBDA
⊂ααααααπαααααααα⊃   ⊂ααααααπααααααααα⊃
~ EVAL ~ LOOKUP ~   ~ EVAL ~ EVALLAM ~
εααααααβααααααααλ   εααααααβαααααααααλ
     # # #               # # #
%αααααα∀αααααααα$   %αααααα∀ααααααααα$
.BOXB
.END
.apart
.APART
.FP
With all this extra mechanism in place, %3eval%1 does absolutely nothing!
.BEGIN SELECT 3;GROUP;CENTER;
.BOXA
eval  <= λ[[exp;env] getget[exp;EVAL] [exp;env]],
.BOXB
.END
.FP
where %3getget%1 looks at  property names associated with %3exp%1
until it finds one which itself has a property list containing %3EVAL%1.

Now real progress has been made.
The evaluation of any expression is controlled by a function associated
with the class to which that expression belongs. It is trivial to modify
or extend such an evaluator: supply the class name and the appropriate
%3EVAL%1 property value.

The technique is applicable to more general kinds of computation than just
evaluation. With a class name we can associate arbitrary pairs of properties
and functions. For example, we might wish to define special input or output
conventions for classes; to do this we simply associate a %3READ%1 property
and a %3PRINT%1 property with the class name and supply routines to
perform the special reading or printing. Similarly, we can associate
a compile property, and a function describing how to compile
instances of this construct.⊗↓The language EL1 (⊗↑[EL1#74]↑) 
incorporates a similar scheme,
however only five designated properties can be associated with any
class name. The techniques of syntax-directed input-output, developed
in {yonss(P105)}, are also applicable to such an evaluator.← 

The net effect of this reworking of evaluation is to expose a much more
general scheme for handling computation.
Such a distributed %3eval%1 is an example of a LISP  technique
called data-driven programming (⊗↑[San#75a]↑).⊗↓The author first
saw this technique used in a non-trivial way 
in ⊗↑[Dif#71]↑ in the Stanford LISP compiler.←  

Property list  representations have also found extensive use in
data base applications ({yonss(P220)}; see ⊗↑[San#75a]↑.
.END "PLEVAL"
.SS(Representation of Property-lists)
.BEGIN "REPPL"
.FP
In discussing representations, we must keep the essential characteristics
of property lists well in mind.  A property list is similar to a local 
environment block; each property list is a sequence of names and
values. However a property list can grow and shrink dynamically, whereas
an environment block is created at a fixed size. Since we cannot
predict the size of the block, a natural representation is  that of a list.


.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
  ⊂αααααααπααααα⊃	  ⊂αααααααπααα⊃  ⊂αααααπααα⊃
  ~ prop1 ~ val1~	  ~ prop1 ~ #αβα→~ val1~ # ~
  εαααααααβαααααλ	  %ααααααα∀ααα$  %ααααα∀αβα$ 
  ~ prop2 ~ val2~        			 ↓
        # # #	               ⊂←  # # # ←ααα←ααα$
			       ↓
  εαααααααβαααααλ      	  ⊂αααααααπααα⊃  ⊂αααααπαα⊃
  ~ propn ~ valn~	  ~ propn ~ #αβα→~ valn~≤'~
  %ααααααα∀ααααα$         %ααααααα∀ααα$  %ααααα∀αα$

   ∞2Property list                   Representation∞*
.BOXB
.END
.FP
The elements of the p-list are associated in pairs. The first element 
of a pair is
the property, the next element is the property value.
But atoms
can't be represented as just any arbitrary list. 
We must be able to recognize the occurrence of an atom so that we can
implement the predicate %3atom%*.  

There are at least two alternatives. We might partition memory as we
began to do on {yon(P159)} with pointer space and atom space.
Then the test of atom-ness is a test on the location being referenced.
We might also  preface the property list with an "atom#header" which will
signal the beginning of the atom. Here the test for atom-ness is a test on the 
contents of the location being referenced.
In the first case we dedicate a section of memory for the storage of 
atoms;⊗↓We need not dedicate a whole section of the machine to "atom space".
Several techniques are available for "mapping" a conceptually 
contiguous  space onto a  scattered memory.⊗↑[Ste#73]↑, ⊗↑[Nor#76]↑,
⊗↑[Pre#76a]↑.← 
in the second case we require an extra memory reference.

A related efficiency consideration involves the use of property lists
in the  implementation of LISP. Since the evaluator will be making frequent
examination of the p-list, it is often useful to store the system-related 
properties  in specific  positions 
relative to the beginning of the p-list; this will eliminate
a search.

Using a separate "atom space", an atom would be represented by its property
list. In this case, property lists 
need not be stored in pointer space. {Yonsec(P210)} examines some of these
techniques. In the text we will describe atoms using the "atom header"
since it makes it clearer in pictures.
Atoms will be  special lists whose
%3car%*-part contains an
indicator used exclusively for the beginning of atoms. 
We will use %b∃%* to designate the beginning of an atom.
The %3cdr%* of the representation of the atom is the representation of
the property list. 
Such locations in pointer space containing %b∃%* in their left-half and
a pointer to a p-list in their right-half are called %2⊗→atom header↔←s%*.

.GROUP
.FP
For example, here is part of a representation 
for the atom for %3car%*:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.TURN ON "?" FOR "\";
.BOXA;KRK
  ⊂ααπαααα⊃   ⊂ααααααπαααα⊃   ⊂αααπααα⊃
  ~∃ ~  #αβαα→~ SUBR ~  #αβαα→~ # ~ # ...→
  %αα∀αααα$   %αααααα∀αααα$   %αβα∀ααα$
 			      	~	
	       	                %→αα→ to machine code for ∞3car∞*
			       
.END
.P50:
.LE(6,Part of the atom-structure for %3CAR%1)
.apart

.GROUP
An example of the distinction between %3get%1 and %3getl%1 in our
representation may be useful.
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
 ∞3getl[FOO;(BAZ)]∞*
         ⊗
∞3getl[FOO;(PNARF BAZ)]∞*                       ∞3get[FOO;PNARF]∞* 
		    ↓				       ↓
        ⊂ααα←ααααααα$				       ~
⊂απααα⊃ ↓ ⊂αααααπααα⊃  ⊂αααααπααα⊃ 		       ~
~∃~ #αβαα→~ BAZ ~ #αβα→~ NIL ~ # ~ 		       ↓
%α∀ααα$   %ααααα∀ααα$  %ααααα∀αβα$ 		       ~
                               ↓		       ~
			     ⊂αααααααπααα⊃  ⊂αααπαα⊃   ~
			     ~ PNARF ~ #αβα→~ # ~≤'~   ↓
			     %ααααααα∀ααα$  %αβα∀αα$   ~
					      ε←ααα←ααα$
					      ↓
					  ⊂αααπαα⊃
					  ~ A ~≤'~
					  %ααα∀αα$
.END
.FP
and %3get[FOO;BAZ] = get[FOO;BAR] = NIL%*.
 Notice how  both %3get%1 and %3getl%1 allow
 free access to the internal representation.
.APART
.BOXB

The simple atom is becoming much more complex. It has a whole substructure
attached to it. Thus each atom is like a word in a dictionary; many words can
be used as different parts of speech and their dictionary entries will
reflect this by having  several alternative meanings. Similarly,
an atom can have several different "meanings" attached to it
and depending on the context, we will be interested in one of those interpretations.
Just as we will find all meanings of a specific word in one location in the
dictionary, our implementation of LISP
becomes much simpler if we store each atom  and its associated p-list uniquely. 
Every reference to the atom %3A%* is actually a pointer to the same
location in memory. This location has a %3car%*-part which is the special 
atom indicator %b∃%*,
and a %3cdr%*-part which is the ⊗→p-list↔← for the atom %3A%*. 
.GROUP
Thus %3(A . A)%*, which we have been writing as:
.FP
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
		⊂αααααπααααα⊃
		~  A  ~  A  ~
		%ααααα∀ααααα$
.BOXB
.END
.FP
might be represented as:
.PT2
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
		⊂αααααπααααα⊃
		~  #  ~  #  ~
		%ααβαα∀ααβαα$
		   ~     ~
		   ~     ~  ⊂απααα⊃
		   %ααααα∀α→~∃~ #αβα→ ∞1p-list for ∞3A∞b 
			    %α∀ααα$
.END
.BOXB
.APART
.P48:
.FP
The internal structures of this implementation of LISP are %6not%* L-trees,
but list structure; that is,
there are intersecting  and circular branches.
LISP implementations therefore involve 
binary list structure since each non-terminal node in our
representation has exactly two branches.

Assume we have the above dotted pair as a value  of a variable %3x%*
and we wish to print the value of %3x%*.
We would expect that an output routine
would be given 
a pointer to the dotted pair and
 we would hope to see "%3(A#.#A)%*" appear on the output  device.
The LISP output routine, named
%3print%*, can recognize that "%3(A#.#A)%1" is a dotted
pair since its %3car%*  is not %B∃%*.
But how can %3print%* distinguish %3(A . A)%* from %3(B . B)%*#?
The pointer in the preceding diagram will point to %3A%* in one case
and to %3B%* in the other, but nothing about the atom tells us %6what%*
to print.  The simplest thing to do  is to store a representation of the name
on each p-list.
This is done with another indicator called ⊗→%3PNAME%*↔←, standing for
%2⊗→print-name↔←%*. Each atom is guaranteed to have  a print-name or "p-name".
The print-name
of the atom is what the LISP output routine will print as the name of 
the atom. 

.GROUP
For example,
the atom %3BAZ%* will have at least the following:⊗↓Since %6every%1 atom
is guaranteed to have a print name, many implementations
separate this property from the general p-list.← 
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
		⊂αααααααπααααααα⊃
	      	~ PNAME ~ "BAZ" ~
		%ααααααα∀ααααααα$
.BOXB
.END
.FP
where %b"BAZ"%1 means a representation of the string of characters, %3B,#A,#Z%1.
.APART

.P216:
When we represent such a property pair we must deal with
representational problems of character strings.
We desire  strings of unbounded length, but must represent them in a machine
with fixed word size. We will discuss a more general representation
in {yonss(P27)}, but here we will represent the print name by using the
basic dotted-pair data structure.

.GROUP
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
		 ⊂αααπαα⊃  
		 ~ # ~≤'~
		 %αβα∀αα$ 
		   ↓
                 ⊂ααααααα⊃ 
		 ~ BAZ≡≡ ~
                 %ααααααα$ 

.END
.LE(6,p-name representation for %3BAZ%1)
.APART
.BOXB
.FP
%bBAZ≡≡%1  means a memory location
containing some encoding of the  letters %bB%*, %bA%*, and %bZ%*.
The symbol, %b≡%*, represents some non-printing character;   
 we
are therefore assuming that  a location can contain five characters.
.GROUP
.FP
We represent the print-name as a list so that we may allow atoms with
p-names of unbounded length. The p-name for %3BLETCH%*, 
would be:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
	 ⊂αααπααα⊃     ⊂αααπαα⊃  
	 ~ # ~ #αβαααα→~ # ~≤'~
	 %αβα∀ααα$     %αβα∀αα$ 
	   ↓		 ↓
         ⊂ααααααα⊃     ⊂ααααααα⊃
         ~ BLETC ~     ~ H≡≡≡≡ ~
	 %ααααααα$     %ααααααα$

.END
.LE(6,P-name structure for %3BLETCH%1)
.BOXB
.APART
.FP
With such print-names on  each property-list
%3print%* can now operate. 
The %3print%1 routine needs the print name and, as we shall see shortly, the
input routine also needs the print name, but otherwise all LISP calculation is
done using the internal pointers to the  property lists.
Several implementations exploit this observation by  placing the print#names
in slower memory than that used for the main computation. Since
access to print names is  infrequent, we can afford to spend more time
in retrieving them.
We will discuss   more of the details of LISP input and output in {yonss(P13)}.

The print-names %bBAZ≡≡%*, %bBLETC%*, and %bH≡≡≡≡%*, should be
stored in atom space since their encodings should not
be interpreted as pointers.
Since "atom space" is no longer an appropriate descriptor
for that space, we will
give it a new name.
We will call that area
of memory which contains information %6not%* to be interpreted as
pointers, %2⊗→Full Word Space↔←%*, and abbreviate it as ⊗→FWS↔←.


In summary, we have  discussed the details of a typical implementation of the
class of S-exprs. Our non-atomic S-exprs have their branching structure
stored in  pointer space. Our initial discussion
of atoms supposed a particular simple representation: simply store the
encoding of the atom in a memory location in a separate space  called
atom space. Upon further reflection we decided that atoms should play
a more active role in the implementation. Since identifiers are to be represented as
atoms, we needed some way to represent those properties typically associated with
identifiers. Identifiers in LISP are, among other things, used for names of 
functions and names of variables. We needed the ability
to represent at least these two kinds of "values" with a LISP atom.
We introduced  the general scheme of property-lists and associated
such a p-list with each LISP atom. All the things we know about a specific
atom are stored on the p-list.  We stored each atom uniquely;
then to examine the properties of an atom only
one structure need be located.
Since all of our LISP programs must be read into the memory, we required that the
input function  keep atoms stored uniquely.
On reading
a literal atom,
the  program checks the current table of atoms.
If the atom appears, the program returns a  pointer to the entry.
If the atom does
not appear it constructs a new  table entry consisting of the  print name.
One  effect unique storage was to turn
our abstract LISP-trees into list structure.
Indeed, the representation of a LISP expression is a
complex net of  pointers; even atoms are now pointers. The only
LISP objects we have represented which are %6not%* pointers are the actual print-names
like %bBAZ≡≡%*.

To  reinforce our  discussion  we illustrate  
the abstract picture of %3NIL%1 and, on  the next  page,  one
implementation  of the atom  %3NIL%*. In  all of the  resulting worms
there are only three elements in Full Word Space; everything else is a
pointer.
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
         ⊂αααααα→αααααα→ααααααα→αααααα→ααααααα⊃
         ↑				      ↓
   ⊂ααα←ααααα←ααααα⊃                          ~
   ↓     ↑         ~     ⊂α←α⊃                ↓
   ~   ⊂αβαπααααα⊃ ↑     ↓ ⊂αβαπααααααα⊃    ⊂αααπααααααα⊃
   %αα→~ # ~ #α→αβ→$     ε→~ # ~ PNAME ~    ~ # ~ CONST ~
       εαααβαααααλ       ↑ %ααα∀ααααααα$    %αβα∀ααααααα$
       ~ # ~ NIL ~       %←αααααα←αααααα←ααααα$
       %αβα∀ααααα$       ↑
         %→αααααα→αααααα→$
.END
.END "REPPL"
.<<pic of NIL>>
.SKIP TO COLUMN 1;
.SS(A Picture of the Atom %3NIL%*,%3NIL%*)
.P141:
We have been writing the atom %3NIL%* as:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.krk
⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπααα⊃  ⊂αααααααπααα⊃  ⊂αααπαα⊃
~∃~ #αβα→~ CONST ~ #αβα→~ # ~ #αβα→~ PNAME ~ #αβα→~ # ~≤'~
%α∀ααα$  %ααααααα∀ααα$  %αβα∀ααα$  %ααααααα∀ααα$  %αβα∀αα$
			  ↓            		    ~  ⊂αααπαα⊃
			 NIL           		    %α→~ # ~≤'~
			                	       %αβα∀αα$
							 ↓
						      ⊂ααααα⊃
						      ~NIL≡≡~
						      %ααααα$
.END

where the atoms for %3PNAME%* and %3CONST%* are represented as:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.krk
⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπαα⊃	⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπαα⊃
~∃~ #αβα→~ PNAME ~ #αβα→~ # ~≤'~	~∃~ #αβα→~ PNAME ~ #αβα→~ # ~≤'~
%α∀ααα$  %ααααααα∀ααα$  %αβα∀αα$	%α∀ααα$  %ααααααα∀ααα$  %αβα∀αα$
			  ↓					  ↓
			 ⊂αααπαα⊃				 ⊂αααπαα⊃
			 ~ # ~≤'~				 ~ # ~≤'~
			 %αβα∀αα$				 %αβα∀αα$
			   ↓					   ↓
			 ⊂ααααα⊃				 ⊂ααααα⊃
			 ~PNAME~				 ~CONST~
			 %ααααα$				 %ααααα$

.END

In full detail, %3NIL%1 is represented as:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.krk
 ⊂ααααααααααααααααααα←ααααααααααααααααααααααααααα←ααααααπααααπααααααααπααα⊃
 ↓							↑    ~        ↑   ↑
⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπααα⊃  ⊂αααααααπααα⊃  ⊂αααπαβα⊃  ↑        ~   ~
~∃~ #αβα→~   #   ~ #αβα→~ # ~ #αβα→~   #   ~ #αβα→~ # ~ # ~  ~        ~   ~
%α∀ααα$  %αααβααα∀ααα$  %αβα∀ααα$  %αααβααα∀ααα$  %αβα∀ααα$  ~        ~   ~
 ↑           %αααααααααα→ ~ →αααααααα→ ~→αα⊃        ~        ↑        ~   ~
 ~			  ↓            ~   ~	    ~  ⊂αααπαβα⊃      ~   ~
 ~			  ~            ↓   ↓	    %α→~ # ~ # ~      ~   ~
 ~			  ↓            ~   ~	       %αβα∀ααα$      ~   ~
 ~			  ~            ~   ~		 ↓            ↑   ↑
 %ααααααα←ααααααααα←αααααα∀αααπαααα⊃   ~   ~	      ⊂ααααα⊃	      ~   ~
                              ↑    ↑   ~   ~	      ~NIL≡≡~         ~   ~
                              ~    ~   ↓   ~	      %ααααα$         ~   ~
 ⊂αααααααααα←ααααααααααααααα← ~ ←α ~ ←α$   ~                          ~   ~
 ↓                            ~    ~       ↓                          ~   ~
⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπαβα⊃  ~	⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπαβα⊃ ↑
~∃~ #αβα→~   #   ~ #αβα→~ # ~ # ~  ↑	~∃~ #αβα→~   #   ~ #αβα→~ # ~ # ~ ~
%α∀ααα$  %αααβααα∀ααα$  %αβα∀ααα$  ~	%α∀ααα$  %αααβααα∀ααα$  %αβα∀ααα$ ~
 ↑           ~		  ↓	   ~		     ~		  ↓       ~
 εααααα←ααααα$		 ⊂αααπααα⊃ ↑		     ↓		 ⊂αααπααα⊃↑
 ~			 ~ # ~ #αβα$		     ~		 ~ # ~ #αβ$
 ~			 %αβα∀ααα$		     ~		 %αβα∀ααα$
 ~			   ↓			     ~		   ↓
 ↑			 ⊂ααααα⊃		     ~		 ⊂ααααα⊃
 ~			 ~PNAME~		     ↓		 ~CONST~
 ~			 %ααααα$		     ~		 %ααααα$
 %αααααααα←ααααααααααααα←ααααααααααααα←αααααααααααααα$
.END




.SS(Input/Output: %3read%* and %3print%*,,P13:)
.TURN ON "←";
.EP;
"...Thus syntax is the servant of sematics, an appropriate
relationship since the substance of the message is conveyed
with the semantics, variations in syntax being an inessential
trimming added on human-engineering grounds. ..."
.PT24;
.BEGIN TURN ON"→";
→Vaughan Pratt, %1#[Pra#73]########
.END
.PT24
.PT24
.PT2
.FP
.BEGIN "FOO";TURN OFF "α";
The implementation of LISP is simplified dramatically since
a very large part of that implementation can be written in LISP itself.
We have already seen that the
evaluation process is expressible this way, and we will exploit this
property again in dealing with compilers#({yonsec(P107)}).


In this section we will show that the majority of the 
 LISP input and output routines can be
written as LISP functions calling a very few primitive routines.
The primitive routines are also  described in LISP,
though they would normally be coded in machine language.

The primitive functions are ⊗→%3ratom%*↔←  and ⊗→%3patom%*↔←.
.BOXA
.BEGIN def
.GROUP
%3ratom[ ]%* is a function of no arguments. It reads the input string, constructing
the next atom
or special character (left paren, right paren or dot).
It looks up that object in the atom table and returns
a pointer to that  table entry.⊗↓Numerals are typically not stored uniquely;
also they are given a simpler structure than the atomic p-list. See {yonss(P293)}
for more details on LISP numbers.←
If no entry
is found an appropriate entry is made.
%3ratom%*  skips over spaces and commas, only
recognizing  them as delimiters. It returns only atoms or special characters
to %3read%*. 
.APART
.GROUP
.def
%3patom[x]%* is a function of one argument expecting an atom, left paren,
right paren, blank, or dot as the value of its argument.
It will print the p-name of that object on the output 
device.
.BOXB
.APART
.END

To  simplify matters, we need to  refer to atoms whose print-names are
the characters "%3)%*", "%3(%*", ".", and " "#(blank).  
We will assume that ⊗→%3RPAR%*↔←, ⊗→%3LPAR%*↔←,
⊗→%3PERIOD%*↔←, and ⊗→%3BLANK%*↔← denote such atoms.  For example, if the next input
character is "(" then
.BEGIN INDENT 4,4,4;GROUP;
.PT2
%3eq[ratom[ ];LPAR]%* is true (and the input pointer is moved to
the next character!).
.PT2
.END
.FP
%3patom[PERIOD]%* will have the effect of printing a %2"."%* on the output 
device.


The LISP %2⊗→scanner↔←%* is %3ratom%1.
A scanner must negotiate with the actual input device for input
characters. The scanner builds the most basic ingredients, like identifiers
  or numbers, and only after
such a basic block has been recognized is the next level of syntax
analysis attempted. 
The units, also called tokens, which the scanner has built are passed  to the
%2⊗→parser↔←%*. 

A  parser 
 determines whether or not
the input stream is a well-formed expression.
The LISP parser is %3read%*;
it builds a tree-representation of the input string,
recognizing both S-expression and list-notation.
.BEGIN "FOO" TABIT2(17,21);TURN OFF"←";SELECT 3;
.KRK
.GROUP
.BEGIN TABIT2(15,20);TURN OFF"←";SELECT 3;
.BOXA
⊗→%3read%*↔← <=λ[[ ]\λ[[j]\[atom[j] → j;
\\ is_lpar[j] → read_head[ ];
\\ %Et%3 → err[ ]]
\[ratom[ ]]]
.BOXB
.END
.BEGIN FILL;select 1;
The call on
%3err%1  will terminate the input scanning
immediately.

%3read_head%* will translate strings %9α%*  acceptable in the context "%3(%9α%1".
Thus %9α%* being %3"A)"%* or %3"A#(B#.#C))"%* would be suitable for %3read_head%*;
%3(A)%* and %3(A#(B#.#C))%* are S-exprs or lists.
%3.#A)%1 would not be acceptable since %3(.#A)%1 is neither an S-expr nor list.
.END
.APART
.GROUP;
.BEGIN FILL;SELECT 1;
.FP
Therefore, if %3read_head%*  sees: 
.END
.BEGIN NOFILL;SELECT 1;TURN OFF "#";
.PT2
\an atom, then %9α%1 is <atom>%9β%3)%1;
.PT2
\a left parenthesis, then %9α%1 is %3(%9β%3) %9∂%3)%1;
.PT2
\a dot, then %9α%1 is %3. %9β%3)%1; this is an error;
.PT2
\a right parenthesis, then %9α%1 is %3)%1 
.PT2
.END
.boxa
.APART
.GROUP
.BEGIN TABIT3(21,26,45);TURN OFF"←";SELECT 3;
⊗→%3read_head%*↔← <= λ[[ ]\λ[[j]\[atom[j] → cons[j;read_tail[]];
\\ is_lpar[j] → cons[\read_head[ ];
\\\read_tail[ ]];
\\ is_rpar[j] → NIL;
\\ %Et%3 → err[ ]]]
\   [ratom[ ]]]
.end
.BOXB
.APART
.GROUP;
.BEGIN FILL;SELECT 1;turn on "#";
%3read_tail%* is looking for legal %9α%*'s in the context "%3(%1<sexpr>#%9α%1".
The structure of this function is that of %3read_head%* except for recognition
of dots. "%3.#%9β%3)%1" %2is%1  plausible in the context "%3(%1<sexpr>#%9α%1".
It is up to %3read_cdr%* to see if its expectations are fulfilled.
.END
.APART
.GROUP
.BEGIN TABIT3(20,25,45);TURN OFF"←";SELECT 3;
.boxb
⊗→%3read_tail%*↔← <= λ[[ ]\λ[[j]\[atom[j] → cons[j;read_tail[]];
\\ is_lpar[j] → cons[\read_head[ ];
\\\read_tail[ ]];
\\ is_dot[j] → read_cdr[];
\\ is_rpar[j] → NIL;
\\ %Et%3 → err[ ]]]
\   [ratom[ ]]]
.END
.APART
.END "FOO"
.BOXB
.GROUP;
.BEGIN FILL;SELECT 1;
.fp
The only input legal after a dot is a S-expr or list followed by a right
parenthesis. Therefore:
.END
.BEGIN TABIT2(20,25);TURN OFF"←";SELECT 3;
.boxa
%3read_cdr <= λ[[ ]\λ[[j]\[is_rpar[ratom[ ]] → j;
\\ %et%* → err[ ] ]]
\   [read[ ]]] 
.END
.APART

.GROUP;select 1;
Finally, here are some of the primitive recognizers which these functions use.
.BEGIN CENTER;SELECT 3;
.PT2
is_dot[x] <= eq[x;PERIOD]     is_lpar[x] <= eq[x;LPAR]%1 
.boxa
.END
.APART

The printing of an internalized   LISP expression is straightforward.
.BEGIN "BAZ" TABIT3(14,20,33);TURN OFF "←";SELECT 3;
.GROUP
.PT2
.BEGIN CENTER;select 3;
⊗→%3print%*↔← <= λ[[x] prin0[x]; terpri[ ]; x] 
.PT2
.END
.FP
%3terpri%1 initiates a new output line. 
.APART
.BOXA
.BEGIN GROUP;SELECT 3;tabit1(20);
⊗→%3prin0%*↔←%3 <= λ[[x][atom[x] → patom[x];
\ %et%3 → patom[LPAR]; prinbody[x]]]
.end
.begin tabit2(21,37);
prinbody <= λ[[x]\prin0[car[x]];
\[null[cdr[x]] → patom[RPAR];
\ atom[cdr[x]] →\patom[BLANK];
\\patom[PERIOD];
\\patom[BLANK];
\\patom[cdr[x]];
\\patom[RPAR];
\%et%3 → prinbody[cdr[x]]]]
.BOXB
.END 
.BEGIN FILL;SELECT 1;
.FP
Notice that we have used the extended 
λ-expressions and conditional expression as described
in {yonss(P253)}.⊗↓Notice too that %3print[(A#.(B#.#C))]%* prints as
%3(A#B#.#C)%1. This is because  %3print%1 doesn't  know that the structure is
not a list until it sees the last dotted-pair. There are two ways of handling this:
either require a type-code, telling whether the structure is a dotted pair or 
a list, represented as a dotted pair. Then %6all%1 dotted pairs are printed in dot
notation, and %6all%1 lists are printed in list notation. The other alternative
is to first examine the structure; if it is a list representation, then print it
that way, otherwise print it as a dotted  pair. This problem is another
indication of "object vs. representation".← 
.END
.APART
.END "BAZ"

The basic %3print%1 routine allows us to print data structures and  program
representations. However the printer will 
print duplications for a list structure which has shared
branches and, worse yet, will not terminate if it is given a 
circular structure. Some implementations of LISP  remedy this ailment; 
see ⊗↑[Ter#75]↑ or ⊗↑[Int#75]↑.

.GROUP;
The output format is a simple linear string
of atoms, numbers, spaces, and parentheses.
For example a %3print%1-based
program for printing function definitions might output the following as the
definition of %3member%1:
.BEGIN FILL;SELECT 3;INDENT 20,20,20;
.P245:
.BOXA
(MEMBER (LAMBDA (X L) (COND ((NULL L) NIL) ((EQ X (FIRST L)) T) (T (MEMBER X (REST L))))))
.BOXB
.END
.APART
.FP
The print routine can break the text at the end of any atom;⊗↓Some implementations
even allow the printer to break in the middle of an atom. This is accomplished
by designating a special character for carriage control, and the %3read%1 routine
knows to ignore the immediately following end-of-line sequence.←  the only
restriction we place on printing of expressions is that what is %3print%1-ed
must be %3read%1-able.

Even with a small definition like this, we have difficulty deciphering
the structure. When functions  or lists become large and deeply nested
then readability becomes impossible. Most implementations of LISP supply
formatting programs called "pretty-printers" or "grinders" to supplement 
the basic print routine.  
.GROUP; 
A pretty-printer might print %3member%1 as:

.BEGIN SELECT 3;TABIT1(13);
.BOXA
(MEMBER
 (LAMBDA (X L) 
  (COND\((NULL L) NIL)
\((EQ X (FIRST L)) T) 
\(T (MEMBER X (REST L))))))
.BOXB
.END
.APART
.FP
See {YONSS(P226)} for a more detailed description of such formatting functions.

So far we have thrown all the I/O back on %3ratom%* and %3patom%*.  Clearly
%3ratom%* will be more interesting. All %3patom%* need do is get the p-name and
print it.  %3ratom%* should perform an efficient search of the atom table and if 
the atom is not found, add it to the table.  All %3ratom%* has to work
with is the actual character string  which
will be the p-name of some atom.  What %3ratom%* could do  is look at the 
p-name of each atom currently in the  table of atoms; when it finds a match
it returns a pointer to that atom; 
this is essentially the linear search scheme of %3assoc%*.
If the appropriate
atom is not found it can build a new one consisting of the p-name, add it
to the table, and return a pointer to this new entry.
In the next section we will introduce an alternative scheme called hashing.
 
.CENT(Problems)
.NL
1.##You might have noticed that the definitions of %3read_head%* and 
%3read_tail%*
are almost identical: the difference involves treatment of dots.
Write new versions of these functions utilizing a common routine and functional arguments.
.NL
2.##Write a set of BNF equations that  
generate the same set of sentences that  %3read%* parses.
.nl
3.##Write a version of %3read%1 which only accepts list notation.
.SS(Table Searching: Hashing,hashing,P14:)
.FP
Table lookup is analogous to  the problem of looking up 
words in a dictionary.  The  scheme of %3assoc%* 
is analogous to  beginning at the first page  of the dictionary and 
proceeding linearly, word-by-word and page-by-page, through
the book until the word in question is found.
More usually, we look at the first character of 
the word and go immediately to the subsection of the dictionary which 
has the words beginning with that character.  We know that if
we cannot find the definition of our word in that subsection we need 
look no further.   We delimit our search even
further by keying on subsequent characters in the word.  Finally
we may resort to linear search to locate the word on a specific
page or column.
A machine might
mimic the dictionary search  and  subdivide the 
table into 26 subsections.⊗↓ That is,
a base 26  sort.← However,
since it is the machine which will subdivide and 
index into the table, there may be  schemes which are computationally  more
convenient for the machine. The scheme should  also
result in rather even distribution of atoms in the subsections. 
If the majority of the atoms end up in the same partition
of the table we will have gained little improvement in the
search efficiency.

An algorithm
used to determine which partition a particular element belongs in is called
a %2⊗→hashing algorithm↔←%* or hashing function.
One obstacle in  such  schemes is the management of each
partition. If more than one element "hashes" to a partition then we
have a %2⊗→collision↔←%1. There are two basic strategies  available
to resolve such a collision. The first, called %2⊗→open addressing↔←%1
involves re-hashing the element, thus refining the partition, until no collision
exists. In the second, called %2⊗→bucket hashing↔←%1, the hashing
function hashes to a "bucket". All the elements with the same
hash number are stored in the 
same "bucket";  a  separate search, perhaps linear search, is used
to discover if an element is in the bucket; and
an element 
 will appear in at most one bucket.  
Since most  LISP implementations use bucket hashing, we will describe that
scheme in more detail.

The search algorithms are applied within %3ratom%1 after an identifier has
been delimited.
All ⊗→%3ratom%*↔← has  at that time is the 
encoding of the actual name of the atom; call that string 
%3chr_str%1.   The hashing function
will use %3chr_str%* to determine which bucket must contain the atom.
Given the bucket number,
we examine the list of atoms in that bucket, comparing
each print-name  against %3chr_str%*.
If a print-name matches, we return a pointer to the property list of that
atom.
If the atom
with print-name %3chr_str%* does not appear in that bucket we are assured
that it does not appear anywhere in the table.  In this case we
create a new atom structure, add it to that bucket, and
the value of %3ratom%1 is a pointer to that new structure.
.GROUP;
Here is a simple hashing function:
.BOXA
.NL
%21.%*##Assume that we have N+1 buckets, numbered 0, 1, 2 ... N.
.NL
%22.%*##Take the numeric representation of %3chr-str%* and
divide that number by N+1.
.NL
%23.%*##Look at the remainder.  It's a number between 0 and N.
.NL
%24.%*##Use that remainder as the index to the appropriate bucket.
.APART;
.BOXB
The LISP atom table, usually called ⊗→%3OBLIST%*↔← (for %2⊗→object list↔←%*),
is a list of buckets.  Each bucket is a list of the atoms which `hash' to that bucket.
We actually represent the object list as an array named %3oblist%*.
Arrays are discussed in full in {yonss(P137)}, but basically are an efficient
storage representation for sequences of fixed length. In this case
we can allocate
a block of sequential cells and use the addressing structure of the  hardware
to do a rapid subscript calculation.
The hash number will give us the array subscript  and we can 
go to the correct bucket immediately;
we won't have to  %3cdr%* down the object list to locate the  bucket.

.GROUP
.P150:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
			⊂αααπααα⊃
  ⊂ααααααα←ααααααα←αααα←βα# ~ #αβα⊃
  ~			εαααβαααλ ↓
  ~			~   ~   ~←$
  ~	   ⊂ααα←ααα←ααα←βα# ~ #αβ→⊃
  ↓ 	   ↓		εαααβαααλ ↓
 ...	(to bucket 2)	  ... ...
  ↓	   ↓		εαααβαααλ ↓
  ~       ...       ⊂α←αβα# ~ ≤'~←$
  ~                 ↓	εαααβααα$  
  ~		    %αα→αα→ααα⊃
  ↓                 	      ↓
(to bucket 1)           (to bucket n)
  ~                 	      ~
  ~		              ~  ⊂αααπααα⊃      ⊂αααπαα⊃
  ~ ⊂αααπααα⊃     ⊂αααπαα⊃    %α→~ # ~ #αβ→ ...→~ # ~≤'~
  %→~ # ~ #αβ→...→~ # ~≤'~   	 %αβα∀ααα$      %αβα∀αα$
    %αβα∀ααα$     %αβα∀αα$	   ↓              %→ ...
      ~             ~		 ⊂απααα⊃
  (to atom 1:      (atom m:      ~∃~ #αβ→(p-list of 
    bucket 1)        bucket 1)   %α∀ααα$  atom 1: bucket n)
      ~		    ↓
      ~           . . .
      ↓     
  ⊂απααα⊃  ⊂αααααααπααα⊃  ⊂αααπααα⊃ ⊂ααααααπααα⊃ ⊂αααπαα⊃
  ~∃~ #αβα→~ PNAME ~ #αβα→~ # ~ #αβ→~ SUBR ~ #αβ→~ # ~≤'~
  %α∀ααα$  %ααααααα∀ααα$  %αβα∀ααα$ %αααααα∀ααα$ %αβα∀αα$
			    ↓			   ↓
			  ⊂αααπαα⊃	   to primitive code
			  ~ # ~≤'~	      for ∞3car∞*
			  %αβα∀αα$
			    ↓
			  ⊂ααααα⊃
			  ~CAR≡≡~
			  %ααααα$
.END
.LE(6,Partial Object List; where atom 1:bucket 1 is %3CAR%1)
.APART
.FP;
Note: Though the top level of %3OBLIST%* is stored sequentially for fast access
by the hasher, the %3cdr%*-parts are chained together in a  sequential 
list so that the  table will have the same structure as any other list. The
chained representation is used by any  LISP process
other than the hasher.⊗↓In particular,
the garbage collector uses this linking. As a further implementation note,
the implementors of MACLISP noted the frequent use of single character atoms
and added a special section to the top-level of the object list. A contiguous
block of cells, of size equal to the number of characters, was added. On reading
a single character atom, the corresponding entry in the table is examined.
A %3NIL%1 says the atom hasn't been seen before; otherwise its p-list
representation resides there.← 
Whether a linear search and storage technique, 
like %3assoc-pairlis%1,
or a more complex technique like hashing should  be employed 
depends on the application, and the speed and size of the machine.
The hash table takes extra space both for storage and for program, but
gives a faster search time. The linear technique requires less space, but
can be quite slow.
Several books cover searching and sorting in great detail (⊗↑[Gri#71]↑, ⊗↑[Knu#72]↑).


MACLISP embellishes the basic %3OBLIST%1 
idea in an important way. That  system will
allow several object lists to exist simultaneously This is useful since several
cooperating LISP subsystems may exist; for example the LISP editor, debugger, and
compiler are all written in LISP and may all be used within the same interactive session.
There is a potential  difficulty since each 
of those subsystems may use names which conflict
with names in the user's programs. Multiple object lists are a way to overcome this
problem.⊗↓Static binding is another way to handle the 
problem.← Only one object list is current at any time, but several may exist in
the system.
Object lists are swapped by
λ-binding to the identifier %3obarray%1.⊗↓An object list is
called object array in MACLISP since the table is represented as an array.
We discuss arrays in {yonss(P137)}.← 
.GROUP;
.BEGIN CENTERIT;SELECT 3;
.PT2
%1Consider:%3←λ[[obarray]%9x%3][ob%41%3]%1
.PT2
.END
.FP
Assuming that %3ob%41%1 is bound to an object list, 
then within the evaluation of %9x%1 the symbols and bindings of
%3ob%41%1 would be accessible.
.APART

Finally, we want to present a  version of ⊗→%3ratom%*↔← which uses a hash
 organization.
In this discussion, we will restrict ourselves to literal atoms, leaving
the reader to supply the necessary parts for recognition of numbers.
.BEGIN GROUP;
We will recognize three classes of characters:
.NL
%21.%1##The class of letters will include the alphabetic characters.
.NL
%22.%1##The class of delimiters consists of those characters which signal
the end of an atom. For this scanner we assume space and carriage control
are delimiters.
.NL
%23.%1##The special characters will consist of "(", ")" and "." .
.END
.PT2
Special characters also act as delimiters in LISP and this results in a
slight complication. Consider the  partial string "%3AB#)C%1". 
Our scanner should scan the "%3A%1", scan the "%3B%1", and scanning the space,
should recognize a delimiter. It
should recognize the %3AB%1 as an atom, and signal %3read%1. The string
will be reduced to "%3)C%1". The next time %3read%1 calls %3ratom%1 the 
right parenthesis will be seen, recognized as a special character and 
an indication of that will be returned to %3read%1.

Now consider the string "%3AB)C%1"; %3ratom%1 will scan "%3A%1" and "%3B%1"
as before. It will then scan the ")". It now needs to do %6two%1 things;
it must signal %3read%1 about the atom it has seen, but it must also
remember  the  ")" so that the %6next%1
time %3read%1 asks for information, it sees the ")" and not the "%3C%1".
We handle this problem by using a global variable named %3lst_chr%1.
This variable is initialized to %3NIL%1 and remains that way until
our anomalous situation occurs. At that time the special character is
placed in %3lst_chr%1, and %3ratom%1 exits normally. So, whenever %3ratom%1
is called, the first thing it does is check the contents of %3lst_chr%1.
If it is non-empty, its contents is returned, as %3lst_chr%1 is set empty
again.
.BEGIN TURN OFF "←";SELECT 3;TABIT2(17,19);
.GROUP;
.BOXA
ratom <=λ[[] prog[[chr]
\\[lst_chr → swap[lst_chr;chr];return[chr]];
\a\chr ← readch[];
\\[is_let[chr] → stuf_buf[chr];return[ratom%41%3[]];
\\ is_delim[chr] → go[a];
\\ is_spec[chr] → return[chr]]]]
.boxb
.BEGIN FILL;SELECT 1;
.FP
This procedure uses  tricks advertised in {yonss(P214)}; it uses
%3lst_chr%1 as a predicate, knows that %3prog%1 variables are
initialized to %3NIL%1, and knows that the representation of %ef%1 is %3NIL%1.
With that knowledge, %3swap%1  swaps the contents of %3chr%1 and %3lst_chr%1.

The routine %3readch%1 gets the next character, and %3stuf_buf%1
is used to save the character string which is to become an atom.
The character string is built up in %3buf%1.
.END
.APART
.END
.BEGIN TURN OFF "←";SELECT 3;TABIT3(20,22,37);
.GROUP
.BOXA
ratom%41%3 <= λ[[] prog[[chr;chr_str]
\l\chr ← readch[];
\\[is_delim[chr] → return[intern[chr_str]];
\\ is_spec[chr] → lst_chr ← chr; return[intern[chr_str]];
\\ %et%3 → stuf_buf[chr]; go[l]]]]
.boxb
.BEGIN FILL;SELECT 1;
.FP
If %3ratom%41%1 sees a special character  it is saved in %3lst_chr%1.
.END
.APART;
.GROUP;
.P277:
.BOXA
intern <= λ[[l] prog[[bucket]
\\bucket ← oblist[hash[maknam[l]]];
\a\[null[bucket] → return[insert[l]]];
\\[right-one[get[\first[bucket];
\\\PNAME];l] → return[first[bucket]]];
\\bucket ← rest[bucket];
\\go[a]]]
.BOXA
.BEGIN SELECT 1;FILL;
.FP
%3maknam%1 takes our character string and converts it into an 
appropriate numeric representation; for example, the input string might
exceed one machine word.
%3hash%* returns the bucket number of its argument, and
%3insert%*   builds the atom and inserts it into a bucket.
%3right-one%* is a predicate used to check if an atom  
has the right print-name.
.END
.END
An implementation of %3ratom%1 may be generalized so that
the class of special characters and delimiters can be  varied. This is
done using  a representation of a character table whose name entries
are characters, and whose value entries determine the %3ratom%1 properties.
This allows LISP users to  define their own parsers and scanners.
LISP's modifiable input routine, coupled with its data structures and
extendible evaluator make LISP an excellent tool for building more sophisticated
language systems.

.P157:
On {yon(P204)} we introduced the abbreviation %9`%3x%1 for %3quote[x]%1.
This %3quote%1 facility is an instance of a device called
a ⊗→%3read%1#macro↔←;
it is the duty of %3ratom%1 to recognize such constructs.
Whenever %3ratom%1 sees the prefix %9`%1 it
reads the next S-expr %9α%1 and returns the list %3(QUOTE %9α%3)%1 as
value. 
In some systems (⊗↑[Moo#74]↑)  users may define their own %3read%* macros.
For example a definition like:
.BEGIN CENTER;SELECT 3;
.BOXA
%9`%3 <%4r%3= λ[[] list[QUOTE;read[]]]
.BOXB
.END
.FP
would signal LISP to change the character table entry for "#%9`%1#" to 
be a %3read%1#macro.
If "#%9`%1#" appeared during  an input operation,
then the body of the %3read%1-macro would be evaluated;
that would call
%3read%1,  and then form a list with %3QUOTE%1 and the result. The resulting list
would be returned to  within the original input process.

MACLISP  also defines a comment facility using a %3read%1#macro.
The occurrence of a semi-colon signals the beginning of a comment; all
characters to the end of the line are taken as commentary.

Several implementations also include abbreviations to decrease 
the number of parentheses
needed. For example "[" and "]" are often defined to be "super-parentheses".
The "[" acts like a "(" but its
scope  runs to the next  "]", constructing sufficient
")" to balance the intervening expression.
Similarly, the scope of a "]" extends to the prior  matching "["; if none
exists, the expression is completed by supplying sufficient ")" to balance.
.GROUP;
.FP
For example:
.BEGIN CENTERit;SELECT 3;
.BOXA
.BEGIN TABIT2(10,32);
\((A B) ((C D E)))\= ((A B) ((C D E))] 
\\= [(A B) ((C D E))] 
\\= ((A B) ((C D E] 
.END
.PT2;pt2
%1and%3←(A [B (C]) = (A (B (C)))
.BOXB
.END
.APART
.END "FOO";

Regardless of the specifics of the implementation, the input routines
will read  a list representation of a LISP expression and 
convert it into an S-expr. For example, 
let's see what happens if we want to evaluate
.BEGIN CENTER;SELECT 3;
.PT2
eq[x;A] 
.PT2
.END
.FP
This will be presented to the machine as:
.P156:
.BEGIN CENTER; SELECT 3;
.PT2
(EQ X (QUOTE A))
.PT2
.END
.APART
.fp
That input will be recognized with the %3read-eval-print%1 loop:
.BEGIN SELECT 3;TABIT3(13,18,20);GROUP;
.BOXA
\prog[[]
\\a\print[eval[read[];( )]];
\\\go[a]] 
.BOXB
.END
.GROUP;
.FP
%3read%1 will begin parsing the sequence of characters; it will 
depend on %3ratom%1 to return indications of the special characters, and
will depend on %3ratom%1 to properly represent each occurrence of an atom.
The parser knows about the representation we have chosen for lists
and will use  %3cons%1 to build up the S-expression form:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
    ⊂ααααπααα⊃  ⊂αααπααα⊃  ⊂αααπαα⊃
    ~ EQ ~ #αβα→~ X ~ #αβα→~ # ~≤'~
    %αααα∀ααα$  %ααα∀ααα$  %αβα∀αα$
			     ~ ⊂αααααααπααα⊃  ⊂αααπαα⊃
			     %→~ QUOTE ~ #αβα→~ A ~≤'~
			       %ααααααα∀ααα$  %ααα∀αα$
.BOXB
.END
.APART
.FP
The references to the atoms
%3EQ, X, A,%1 and %3QUOTE%1 are actually pointers to the
atoms. 
Each atom is located only once by the reader. After that we have direct access to
atom and its property list.

Since the input routines perform several %3cons%1 operations; we should look at 
the details of %3cons%1.
.SS(A First Look At ¬3cons¬1)
.FP
The  ⊗→%3cons%*↔← operation is quite different from 
 the other LISP primitives.  The other primitives
 manipulate existing S-expressions, whereas %3cons%*
must construct a new S-expression from two existing  S-exprs.
Given  representations of two S-exprs, say %3x%* and %3y, cons[x;y]%*
must get a new cell, put a pointer to the representation of %3x%* in the 
%3car%*-part of 
the cell and a pointer to the representation of %3y%* in the %3cdr%*-part 
and return a pointer to the new cell:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	∞1result of ∞3cons[x;y]∞B
		~
		~	   ⊂αααααπααααα⊃
		%ααααααααα→~  #  ~  #  ~
			   %ααβαα∀ααβαα$
			      ~     ~
			 ⊂αααα$     %αααα⊃
			 ~ 		 ~
			 ↓		 ↓
	             ∞1rep. of ∞3x                  ∞1rep. of ∞3y∞1
.BOXB
.APART
.END
Before computation
is begun, only the atomic structure for the initial LISP system table
uses cells in the pointer#area. The remaining pointer#cells 
are linked together and form  the %2⊗→free space list↔←%* or FS list.⊗↓%1LISP
free space  is an instance of "heap#storage"#(⊗↑[Alg#75]↑). The 
rationale for heap 
storage is that  storage usage is not sufficiently  disciplined 
that its allocation and deallocation can be predicted. Therefore
some more global management scheme is required.← 
Whenever  %3cons%* needs a cell, the first cell in the FS list is used and
the FS list is set to the %3rest%* of the FS list. 
.GROUP;
.FP
For example the following represents the effect of %3cons[A;B]%* 
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
   ∞3env∞*            ∞3dest∞*          
   ↓		  ↓		  
⊂ααπαα⊃        ⊂ααααα⊃		   
~  ~ #α→...    ~   #αβα⊃
εααβααλ        εααπααλ ~
~  ~ #β→⊃        ...   ↓
εααβααλ ↓      ~  ~  ~←$
~  ~ #βαααα⊃   εααβααλ           Pt∞4FS∞*
%αα∀αα$ ↓  ↓     ...		 ↓
        ~  ~   %αα∀αα$		 ~
        ~  %→αα→α→⊃		 ~
        ↓         ↓              ↓
    ⊂απααα⊃     ⊂απααα⊃       ⊂ααπααα⊃ ⊂ααπααα⊃      ⊂ααπαα⊃
    ~∃~ #αβ→... ~∃~ #αβ→ ...  ~≤'~ #αβ→~≤'~ #αβ→ ...→~≤'~≤'~
    %α∀ααα$     %α∀ααα$       %αα∀ααα$ %αα∀ααα$      %αα∀αα$
     atom A      atom B 
.PT2
.le(6,Before)
.END
.APART
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
   ∞3env∞*            ∞3dest∞*          
   ↓		  ↓		  
⊂ααπαα⊃        ⊂ααααα⊃		   
~  ~ #α→...    ~   #αβα⊃
εααβααλ        εααπααλ ~
~  ~ #β→⊃        ...  ←$
εααβααλ ↓      ~  ~ #ααα→ααα→ααα→⊃
~  ~ #βαααα⊃   εααβααλ           ↓  Pt∞4FS∞*
%αα∀αα$ ↓  ↓     ...	         ~   ↓
        ~  ~   %αα∀αα$	         ~   %ααα→⊃
        ~  %→α→α→⊃	         ~	  ~
        ↓        ↓               ↓        ↓
    ⊂απααα⊃     ⊂απααα⊃       ⊂αααπααα⊃ ⊂ααπααα⊃     ⊂ααπαα⊃
    ~∃~ #αβ→... ~∃~ #αβ→ ...  ~ # ~ # ~ ~≤'~ #αβ→...→~≤'~≤'~
    %α∀ααα$     %α∀ααα$       %αβα∀αβα$ %αα∀ααα$     %αα∀αα$
      ↑           ↑             ↓   ↓
      %αααα←αααα←αααα←αααα←ααααα$   ~
		  ↑                 ↓
		  %←ααααα←αααα←ααααα$
.PT2
.le(6,After)
.END

As the computation continues, cells are taken from the FS list.
When a %3cons%* operation needs  a cell and the FS list is empty, the
computation is suspended and a %2⊗→storage reclaimer↔←%* 
is called. The reclaimer is  often known by a more
colorful name:#the %2⊗→garbage collector↔←%*.
The job of the garbage collector is to locate cells for a new
FS list.

.SS(Storage Management: Garbage Collection,garbage collection,P146:)
.FP
During the course of a computation, contents of cells which were taken 
from the FS list often become unnecessary. For example, if we ask LISP to evaluate
something as simple as:
.BEGIN CENTERIT;
.PT2
←%3(CONS (QUOTE A) (QUOTE B)),%* many cells are used:
.PT2
.END
.GROUP;
.NL
%21.%*##At least seven cells are needed just to read in the expression:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
⊂ααααααπααα⊃  ⊂αααπααα⊃  ⊂αααπαα⊃
~ CONS ~ #αβα→~ # ~ #αβα→~ # ~≤'~
%αααααα∀ααα$  %αβα∀ααα$  %αβα∀αα$
		↓	   ↓ ⊂αααααααπααα⊃  ⊂αααπαα⊃
		~	   %→~ QUOTE ~ #αβα→~ B ~≤'~
		~	     %ααααααα∀ααα$  %ααα∀αα$
		~  ⊂αααααααπααα⊃  ⊂αααπαα⊃
		%α→~ QUOTE ~ #αβα→~ A ~≤'~
		   %ααααααα∀ααα$  %ααα∀αα$

.BOXB
.END
.APART
.fp
If some of the atoms are not present in the atom table,
more cells will be needed.
.NL
%22.%*##One cell will be needed to perform the %3cons%* operation. See 
the previous example.

After the computation is completed, LISP will print "%3(A#.#B)%1"
and wait for more input. After the %3print%1 statement is completed
none of the eight mentioned cells are needed.
They are garbage.
In the current example, these "garbage  cells" could have been explicitly 
returned to the free list, but
in general it is difficult to know exactly which cells
%6are%* garbage.⊗↓Experiments have been performed in which LISP
programmers were allowed to return "garbage" to the FS list themselves.
The results were disastrous; list structure thought to be garbage 
was returned to the FS list even though  the structure was still being
used by other computations.← In {yonss(P171)} we will see how these difficulties 
can arise.

The responsibility for
reclamation is  therefore passed to the LISP system.  The %3cons%* procedure
removes cells from the FS list, and
its FWS counterpart  %3fwcons%*,
removes cells from the FWS list when making numbers or print-names.
These two functions  are the only functions allowed
to manipulate the free storage lists.  When either list becomes empty, the
garbage collector is called.  
.GROUP;
.BOXA
.begin center
%2The fundamental assumption of garbage collection is:%*
.end
.boxa
.begin
.indent 10,10,10
At any point in a LISP computation, all cells which contain
parts of the computation are reachable (for example, 
through %3car-cdr%* chains)
from a fixed set of known cells or base registers.
.BOXB
.end
.APART
The first phase of the garbage collector, called the %2⊗→marking phase↔←%*,
marks all of the list structure which is currently active. 
By definition, a
 cell is active if it is reachable from the base registers.
The base registers include:  pointers to  the beginning of the atom table and
the environment chain; a pointer to the control chain is 
also included  since partial results are stored there.
Active cells therefore include all the
atoms in the atom table and all the associated elements on property lists.
Any partial computations which have been
generated will also be marked. 


In terms of our implementation, we mark from the object list, from %3dest%1,
 and from %3control%1 (see {yon(P200)}). 
If deep binding is used, we mark the elements reachable
through %3env%1.
If shallow binding is used, then  marking of %3oblist%1
would capture all the values; even the ones which may not be accessible
as λ-values. What we should do instead  is mark the non-value properties
on atoms using  %3oblist%1; we then mark 
the values separately using the current %3env%1 skeleton tree.

A structure might be referenced several times in the marking process, since
we allow shared structure, and since the implementation will  be referencing
structures also referenced by the user's program. We must take this into account
since, though naive marking of an already marked structure is  at  wasteful, 
it is  fatal if the structure is self-referential.
Once all the active structure has been
marked, we proceed to the  %2⊗→sweep phase↔←.%*

The sweep phase proceeds linearly   through memory,
collecting all those cells which have %6not%1 been marked.⊗↓The sweep phase is
sometimes a good place to unmark the marked cells.  This depends on the 
implementation. If each word carries a "mark#bit" then, 
perform the unmarking; if
the marked flags are all localized in a separate bit table#({yonss(P263)})
then there is no advantage to   doing the unmarking now.← 
These unmarked cells are chained together via their %3cdr%*-parts to form 
a new FS list. The FS pointer is set to the beginning of this list.
The unmarked cells in FWS  comprise the new FWS list.

If there is sufficient room in a full word to contain a pointer, then we
chain the words together; otherwise we must designate the FWS list
some other way.

Garbage collection is a very general storage management technique.
It has become a standard tool for implementors of complex systems. It was 
invented by the original LISP implementation team.
The basic ideas have been embellished over the years to account for larger 
real memories, virtual memories, different implementations of LISP data,
and different machine architectures; but the basic ideas are simple.
More complex 
algorithms will be discussed in {yonss(P27)} and on {yon(P144)}.
.SS(A Simple LISP Garbage Collector,,P280:)
.FP
We will now write a garbage collector in LISP to mark and sweep nodes
in FS and FWS.
.GROUP;
.FP
The algorithm will have three main functions:
.BOXA
.BEGIN def;GROUP;
%3initialize[x;y]%*  initializes the marking device for each cell in the space 
between %3x%* and %3y%*.
%3initialize%* will be called twice; once for FS and once for FWS.
The next algorithm does the actual marking.
.END
.begin def;group;
%3mark[l]%* will be called for each base register %3l%1 which points to 
active  list structure.
If the word is in FWS %3mark%1 will mark it and return;
if the word has already been marked  it simply return,
since we are assured that any cells further down the structure
have already been marked. Otherwise the word is
in FS and thus has a %3car%* and a %3cdr%*; mark the word; 
recursively mark the %3car%*;
recursively mark the %3cdr%*.
.end
.APART;
.BEGIN def;GROUP;
%3sweep[x;y]%*  collects all inaccessible cells in the space delimited 
by %3x%* and %3y%*.
%3sweep%* will be called twice; once to generate a new free space list and once
to generate a new full word space list. Elements of these free 
lists will be chained together by their %3cdr%* parts.
The initialization and sweep phases of this garbage collector are very similar and,
as we mentioned above, can sometimes be combined.
Both these phases must be assured of reaching every node in the space.
.END
.BOXB
.GROUP;
.FP
These main functions use several other functions and predicates:
.BOXA
.BEGIN INDENT 0,6;
%3fwswrdp[x]%* is true just in the case that %3x%* is a word in FWS. This is
used as one of the termination conditions of %3mark%*.
.PT18
%3markA[x]%* marks word %3x%* as accessible.
.PT18
%3markNA[x]%* marks word %3x%* as not accessible.
.PT18
%3Ap[x]%* is true if word %3x%* is marked "accessible".
.PT18
%3up[x]%*: If %3x%* is at location %bn%* then %3up[x]%* is location %bn+1%*.
.PT18
%3rplacd[x;y]%* modifies %3x%* by replacing its %3cdr%1-part with %3y%*.
The value returned is the new %3x%1.
.BOXB
.END
.APART;
.P246:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK
   ∞3dest∞*	     		       ∞3env∞*
    ~				   ~
    ~	⊂ααααααα⊃		   ~	⊂ααααααα⊃
    %→  ~     #αβα⊃ 		   %→   ~     #αβαα ### →
	εαααπαααλ ↓			εαααπαααλ 
          # # #	 ←$			~ x ~ # βα→α⊃
	~   ~   β→ - - →⊃		εαααβαααλ   ~
	εαααβαααλ  	  		~ y ~ #αβ→⊃ ↓
        ~   ~   ~	↓               %ααα∀ααα$ ↓ ~
          # # #	      ⊂αααπααα⊃	        ⊂ααααααα⊃ ~ ↓
       	εαααβαααλ     ~ ? ~ # β→ - - - →~   ?   ~←$ ~
        ~   ~   ~     %ααα∀ααα$	        %ααααααα$   ~
       	%ααα∀ααα$ 	↑	                    ↓
		        %←ααααα←αααα←ααααα←ααααα←ααα$
.LE(6,Algorithm for ∞3rplacd∞1)
.END
.PT2
.FP
Can you write %3rplacd%* as a LISP function?

.BEGIN SELECT 3;TABIT2(19,22);TURN OFF "←";GROUP
.BOXA
initialize <= λ[[x;y] prog[[]
\ a\markNA[x];
\\x ← up[x];
\\[eq[x;y] → return[%et%3]];
\\go [a]]]
.PT2
.END
.BEGIN SELECT 3;TABIT2(19,24);TURN OFF "←";GROUP

mark <=    λ[[l]\[Ap[l] → %et%3;
\ fwswrdp[l] → markA[l];
\ %et%* →\markA[l];
\\mark[car[l]]; 
\\mark[cdr[l]] ]]
.PT2
.END
.BEGIN SELECT 3;TABIT2(17,20);TURN OFF "←";GROUP
.P257:

sweep <= λ[[x;y] prog[[z]
\ a\[not[Ap[x]] →  z ← rplacd[ x;z]];
\\x ← up[x];
\\[eq[x;y] → return [z]];
\\go[a]]]
.BOXB
.END

As indicated previously, there are alternatives  to garbage collection.
If the data-structure manipulations are particularly simple
one might leave storage management to the
 programmer.⊗↓Aside from these implementation
considerations, one strong point of LISP is the notion that storage
management need not concern   symbolic programmers to any larger extent
than roundoff errors concern their numerical counterparts.←
.P145:
There is
an intermediate area between garbage collection and explicit management.
First notice that storage management becomes quite simple if there is no sharing
of sublists.   However 
sharing substructures can save space and careful modification of shared structures
can communicate global information between algorithms.
A rich class of symbolic data manipulations fall into the  category of
shared, but non-circular, structures. In this case, storage can be managed
by the %2reference counter%1 method.

Instead of using a garbage collector, we might  associate a counter, called
a %2⊗→reference counter↔←%*, with each
list when it is built. In that counter we will store the number of references
to that list. The counter will be initialized to 1 when the list is created.
Whenever the list
is shared we increase the counter by 1; whenever the list is no longer to
be shared by  some list structure,  we decrease the counter by 1.
When the count goes to 0 we can put the cells of the list in the free space list.

A difficulty with the  reference counter scheme is the
inability to collect
circular lists. A circular list is a list structure  which is 
self-referential.⊗↓LISP 1 (⊗↑[McC#60]↑) disallowed circular list, but succeeding
LISP dialects have  allowed arbitrary binary structure.← 
Consider the following sequence:

.BEGIN NOFILL;GROUP;TURN OFF"←";
.NL
%21.%*##Manufacture a list, %3x%*: %3x ← (B I G L I S T)%1. Reference count is#1.
.NL
%22.%*##Circularize it: %3x ← circle[x];%*.  Reference count is now 2.
.NL
%23.%*##Delete all references to %3x%*: %3x ← NIL%*. Reference count reverts to 1.
.PT18
.END
.FP
The list is no longer referenced, 
but it is not on the free space list, and has thus
been lost to the system.

Two less serious considerations should be mentioned in conjunction with
reference counters. First, each node which is to be collected with this scheme
must have an associated reference field to contain the count. That requires
extra space, and usually imposes a maximum size for the reference count.
If that maximum is reached,
either an additional space is allocated, or 
the filled count may never be decremented and the associated 
structure must be garbage collected.

The second problem involves  decrementing counts. Whenever a count goes to zero
the counts associated with its immediate successors must also be decremented.
This process is applied recursively until non-zero counts are encountered.
The bookkeeping for such a task is non-trivial.

There are significant storage management problems which
are amenable to  reference counting. LISP generates
very intertwined structures; therefore these
alternative methods are insufficient in general. 
However, some  parts of LISP implementations
could use reference counting; we will discuss some of 
these aspects in {yonss(P228)}. For an excellent discussion 
and analysis of storage
management schemes see ⊗↑[Mul#76]↑.
.CENT(Problems)
.P154:
.NL
1.##This problem deals with what is known in LISP as %2⊗→hash consing↔←%* 
(⊗↑[Got#74]↑).
We have been storing atoms uniquely, but it should be clear from the behavior
of %3cons%* that non-atomic S-exprs are %6not%* stored uniquely.
Storing single copies of any S-expr would save space. For example,
the non-atomic structure of
%3((A#.#B)#.#(A#.#B))%* could be represented with two cells rather than three.
Unique storage is not without its difficulties. What problems do you foresee
in implementing such a scheme? 
.NL
2.##We said on {yon(P48)} that many LISP computations generate list structure
rather than true LISP-trees. Give an example.
.P55:
.NL
3.##Can you write a LISP function %3circle <= λ[[x] ...]%* which will take
a list %3x%* and make it circular. Thus:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK;BOXA
			     ⊂ααααααααααααα←ααααααααααααα⊃
⊂αααααααααπααα⊃  ⊂αααααπααα⊃ ↓ ⊂ααααπααα⊃  ⊂αααααααπααα⊃ ↑
~ NOTHING ~ #αβα→~ CAN ~ #αβα∀→~ GO ~ #αβα→~ WRONG ~ #αβ→$
%ααααααααα∀ααα$  %ααααα∀ααα$   %αααα∀ααα$  %ααααααα∀ααα$
.END
.BEGIN INDENT 4,4
This list is circular on its "last two" elements.
Printing such structures is not possible using the  %3print%1 function.
.END
.NL
4.##What LISP operations generate  structures such that a reference
counter implementation would not suffice?
.next page;
.SS(A Review of the Structure of  the LISP Machine,LISP machine)
.FP
We have a good portion of the storage conventions for LISP set out.
A difficult area involves the organization of the data structures
to perform the correct binding and unbinding of variables. Before
we tackle that, we give a diagram showing the basic structure of LISP
memory.
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.TURN ON "?" FOR "\";
.TABS 62;
.BOXA;KRK
	⊂αααααααααααααααααααααααααααααααααααααααα⊃
	~?~
	~      ### THE SUBCONSCIOUS ###?~
	~ ∞3eval∞* and friends?~
	~ ∞3read∞* and ∞3print∞*?~
	~ the garbage collector?~
	~ the base registers for marking;?~
	~    these include: ?~
	~   FS pointer?~
	~   FWS pointer?~
	~   atom table(∞3OBLIST∞*) pointer?~
	~   registers for partial results?~
	~     ∞3dest, control∞*?~
	~   the access chain?~
	~?~
	εααααααααααααααααααααααααααααααααααααααααλ
	~?~
	~      ### POINTER SPACE ###?~
	~  the free space list?~
	~  those parts of S-exprs containing?~
	~    ∞3car∞*- and ∞3cdr∞*-parts.?~
	~?~
	εααααααααααααααααααααααααααααααααααααααααλ
	~?~
	~       ### FULL WORD SPACE ###?~
	~   the full word space list?~
	~   atom print names?~
	~   numbers?~
	~?~
	%αααααααααααααααααααααααααααααααααααααααα$
.BOXB
.END
.LE(6,Structure of LISP memory)
.APART
.SS(Implementations of Binding,,P78:)
.FP
In {yonss(P6)} and {yonss(P134)} we discussed deep binding and shallow binding
respectively. That discussion took place at a reasonably abstract level.
The next few  sections
discuss these binding implementations in more detail.
We first examine  some of the possible pitfalls in the implementation of LISP;
then we  give deep and shallow implementations for an important subset of LISP.
Finally, we   sketch  some of the  methods available for implementing the full
language in an efficient manner.

Though much of this discussion deals with the binding stategies of LISP, 
and therefore with control structure, we are restricting ourselves to the
data structure requirements. The next chapter shows how 
the control structures of LISP implementations manipulate these data structures.

.GROUP;
.BEGIN tabit1(10);SELECT 3;centerit
.BOXA
%1Consider the evaluation of a form: ###%3f[a%41%*; ... ;a%4n%3]
.PT2
%1where:%3\f <= λ[[x%41%*; ... ;x%4n%*] ... g[ ... ] ... ;i[ ... ]],
.PT2
\g <= λ[[ ... ] ... h[ ... ] ], 
.PT2
%1and %3\i <= λ[[ ... ] ... j[ ... ] ]
.BOXB
.END
.APART
.GROUP;
.FP
Typically  a picture like the following occurs, where the
instance of function name means a block of λ-bindings necessary to
begin evaluation of that function:

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK
.BOXA
		      ⊂ααα⊃                       ⊂ααα⊃
  		      ~ h ~                       ~ j ~
	       ⊂ααα⊃  εαααλ  ⊂ααα⊃         ⊂ααα⊃  εαααλ   ...
               ~ g ~  ~ g ~  ~ g ~         ~ i ~  ~ i ~
	⊂ααα⊃  εαααλ  εαααλ  εαααλ  ⊂ααα⊃  εαααλ  εαααλ   ...
	~ f ~  ~ f ~  ~ f ~  ~ f ~  ~ f ~  ~ f ~  ~ f ~
	%ααα$  %ααα$  %ααα$  %ααα$  %ααα$  %ααα$  %ααα$ 
.BOXB
.END
.APART;
.FP
We build up a stack of λ-binding blocks as we continue to enter procedures, and
as we leave a procedure we remove that block of bindings from the stack.
When we wish to know the value of a variable we look down the stack for the
first occurrence of that variable; the associated binding is the desired value.
However,
LISP allows functional arguments and functional values; these constructs
require modification of the behavior modelled in this simple blocks world.

When we recognize a functional argument, we note the block which is currently
on the top of the stack. When we apply that functional argument, intervening
blocks will have been stacked; we change the environment such that the lookup
of non-local variables
takes place beginning with the saved block, rather than 
with  the top of the stack.

However, if %3h%* say, generated a functional value which is to be applied
in the context of %3j%* then
we must  retain those
values in the %3f-g-h%* stack in such a way that they may be used to restore
the enviroment when we desire to apply the functional value in the %3f-i-j%* stack.
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
		      ⊂ααα⊃  ⊂ααα⊃
  		↑     ~ h ~  ~ j ~   ~
		~     εαααλ  εαααλ   ↓
           bind ~     ~ g ~  ~ i ~   ~ unbind
                ↑     εααα∀αα∀αααλ   ↓
	        ~     ~     f    ~   ↓
		      %αααααααααα$
.BOXB
.END
.FP
We will discuss data structure requirements for 
implementation of these three LISP subsets: first, simple function
application; then, functional arguments; and finally, functional values.




The mechanism which we described in  the initial blocks model 
occurs quite naturally in computer science. 
It  is called a %2⊗→stack↔←%*.⊗↓Stacks are closely related to
a theoretical device called  a  push-down automaton. There, only the top element
of the stack is accessible. We take a more pragmatic position, allowing
access to elements within the stack, and indeed modification of
elements within the stack; but removal of elements
from within the stack is not allowed. To remove an element, we must
first remove the elements above it.← 
The important characteristics of stacks are that they are lists such that
additions and deletions can only be made at the front of the list.

What is of interest to us now is that stacks have a particularly 
efficient implementation; due to the very regular way in which stacks are
manipulated, the ⊗→linked allocation↔← implementation is not 
usually necessary.⊗↓The typical model for a stack is a contiguous block of memory
but that ignores the question of exceeding the bounds of that 
memory allocation. A stack can be implemented in a discontinuous fashion 
(⊗↑[Bis#74]↑)
as long as the  stack manipulating functions are able to cope with such
behavior. The degenerate case of such discontinuous stacks is a
linked allocation scheme.← 
Instead a stack can be implemented as: 
.BEGIN INDENT 10,10;GROUP
.PT18
%21.%*##A sequence of contiguous locations.
.PT2
%22.%*##A pointer initialized to point %6before%* the first of these locations.
.PT2
.END
.BEGIN INDENT 10,14;GROUP
%23.%*##An operation, typically called %2push%* which places a new
object in the stack. This can be accomplished by 
adding 1 to the value of the stack pointer, and then
putting a representation
of the object in the cell currently referenced by the pointer.
.PT2
%24.%*##An operation called %2pop%* which gets the first value in the stack
and then decrements the pointer by 1.
.PT2
%25.%*##Though the abstract structure  of a stack does not involve 
limitations on the length of stack-space,
any  representation should include techniques
for assuring that the stack pointer stays within its allotted space.
See the preceding footnote.
.BOXB
.END


Notice that the %3concat%* operation can be interpreted  as %6pushing%1
and the %3rest%* operation as %6popping%1. Indeed our earlier manipulations
of symbol tables effectively used such stack operations. 
This is particularly apparent in the representation
of symbol tables given  on {yon(P43)}.


.GROUP;
We will discuss the binding process in terms of a
sequence of three events:
.BEGIN 
.def
%21.%1##%3bind%1  describes what the implementation does
when we are ready to call a procedure. The actual parameters are evaluated
and we are ready to add them to the environment and evaluate the body of the
procedure.
.def
%22.%1##%3lookup%1 will determine how values are located in the current environment.
.def
%23.%1##%3unbind%1 will describe what has to be done as we prepare to exit from
a procedure.
.pt18
.END
.APART
.SS(Stack Implementation of a LISP subset: Deep Bound,,P148:)
.begin "deep"
.FP
The stack implementation of simple function application is a
straightforward implementation of our blocks picture.
We have two stacks which operate  synchronously. One stack is called
the %2⊗→name stack↔←%1; the other is called the %2⊗→value stack↔←%1.
The name stack  maintains the λ-variables (and
generated names, if a primitive is called). The top of the name stack
defines the origin of the environment. When the value of a variable is 
requested %3lookup%1 proceeds down the name stack, looking for the first
occurrence of the variable. The corresponding position in the value stack
contains the desired value.

When we recognize a function  application, we begin the evaluation of the
actual parameters. As each parameter is evaluated, the result is pushed into the
value stack. When all the parameters have been evaluated, we are ready to evaluate
the body of the expression. At that point %3bind%1 pushes the λ-variables onto the name
stack.
When we complete the evaluation of the body of the expression 
%3unbind%1  pops the λ-variables
from the name stack, and pops their values from the value stack.

.GROUP;
Since the λ-variables are  removed from
 the stack as a group we can sometimes speed  up the operation
by storing block sizes in the  stack. Also, the word size of the machine may
allow using one stack for both names and values. For example:


.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
	        ⊂ααααααααααααα⊃
		~      #ααα→ααβ→⊃
	     	εαααααααπαααααλ ↓
	        ~ namen ~ valn~ ~
		εαααααααβαααααλ ~
	             # # #	↓
	        ~ name2 ~ val2~	~
		εαααααααβαααααλ	~
	        ~ name1 ~ val1~ ↓
	       	εααααααα∀αααααλ ~
	        ~             ~←$
		~      #ααα→ααβ→⊃
				↓
.BOXB
.END
.APART
.FP
where %bval1%1 is furthest down the stack since it was pushed on first,
and where all references to %bnamei%1 and %bvali%1 are really pointers to
 appropriate S-expressions (atoms or dotted pairs).
The "back pointer" is used for removing  blocks of bindings, but it is also
a representation of the control link discussed in {yonss(P77)}.

A slight modification of this scheme is sufficient to support 
implementation of functional arguments. An  additional piece of information
is added to
guide  %3lookup%1 in its search for the next block of bindings.
Instead of proceeding linearly down the stack, %3lookup%1 proceeds linearly
through a block and at the end of each block is information telling %3lookup%1
where the next block of bindings is to be found. Recall that information
is called the access link ({yonss(P77)}).

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.boxa;krk
		        ⊂ααααααααααααα⊃
		      ⊂←β←αα#     #αα→β→⊃
		      ↓	εαααααααπαααααλ ↓
		      ~ ~ namen ~ valn~ ~
		      ~	εαααααααβαααααλ ~
       access links   ↓      # # #	↓   control links
		      ~ ~ name2 ~ val2~	~
		      ~	εαααααααβαααααλ	~
		      ↓ ~ name1 ~ val1~ ↓
		      ~	εααααααα∀αααααλ ~
		      %→~             ~←$
		      ⊂←β←αα#     #αα→β→⊃
		      ↓			↓
.boxb
.END

In simple function application, 
the access links and control links are identical.
The evaluation of a functional argument  will generate an access link, pointing
to the current   stack.
That is,
the %3function%1-construct 
is responsible for saving the binding environment
 by saving a pointer to the current top of the name  and value
stack.
When a functional argument is applied, the access link will be set to
that saved
 binding environment ({YON(P215)}).  
Since we are restricting attention to functional
arguments, we are assured that the application of that argument will occur
within an expression which dynamically surrounds the creation of the
functional argument. This means that our environment pointer will indeed be a
pointer down the stack. The use of functional values invalidates that assumption.
Before examining that problem we will discuss shallow binding for
these same LISP subsets.
.end "deep"
.SS(Stack Implementation of a LISP Subset: Shallow Bound,,P225:)
.BEGIN "SHAL"
.FP
A stack implementation of shallow binding allows some  elegant economies.
We can use a stack implementation for the first shallow binder of
{yonss(P134)}.
There we had a collection of bindings associated with the identifier.
Without loss of generality,
we can organize %3mkenv%1 such that the new binding is added in front
of any previous binding.
Now if we are only 
evaluating simple function  applications, %3lookup%1 will find 
the desired binding
provided the unbinding operation removes the first binding as it exits the procedure.
In this way, binding and unbinding 
act on the value entries in a stack-like fashion.
Instead of associating a separate stack with each variable and accessing
the value through the top of the stack, we associate a single value cell
with each variable and store the saved  values of all variables 
on a common stack.
The "shallowest" of the shallow schemes, which only used the
value cell, can also be extended to handle functional arguments.


The implementation of %3lookup%1 will be
simple for either shallow scheme: take the value in the value cell.
Since the value cell will be maintained to %6always%1 contain the 
proper binding of a variable,  the distinction between local and
non-local variables vanishes. The contents of the value cell is  %6the%1
current value for any variable.

We first review the process of shallow binding with the value cell, including the
details we added in {yonss(P209)}. When an application is recognized
we allocate a block to contain the values of the actual parameters; that
is the %3dest%1 block. As the arguments are evaluated, the results are sent
to the appropriate slots in the %3dest%1 block.⊗↓This scheme will also
work with multi-valued functions.←  
When all the arguments are evaluated, we link the %3dest%1 block onto the
front of the environment, but as we do that we %6swap%1 the current contents of the 
affected value cells with the new values. 
This establishes the new values in the value cells
while saving the prior bindings. We are now  ready to evaluate the body
of the application. When evaluation is completed we swap %6back%1, using the
first block of the saved environment chain; then we remove that
first block from the chain. Since we are assuming a simple function call,
 that old %3dest%1 block  is no longer accessible and can be collected.⊗↓Since
the %3dest%1 block is no longer accessible, it was unnecessary to %6swap%1
back; we could have  simply %6restored%1 the value cells. The swap
was described in preparation for more general implementations.← 
The allocation and de-allocation process is   stack-like;
we will develop our implementation using 
a stack called  the Special Pushdown stack.
  This stack will be referenced by a  stack pointer
called %bSP%1 or  called %bENV%1 when we wish to  reinforce its relation to the
more general environment structures.


.GROUP;
In the spirit of the evaluator of {yonss(P209)}, we would evaluate
%3λ[[x;y]#%9x%3][C;D]%1 as follows:

.NL
%21.%1##Allocate space for the parameters %3x%1 and %3y%1. This space
is reserved on the top of the %bENV%1 stack, and is referenced by a pointer
named %bDEST%1.
.APART;
.GROUP;
.NL
%22.%1##Evaluate the actual parameters and send the results to the %3dest%1
block.
.NL
%23.%1##Swap the contents of the value cells for %3x%1 and %3y%1
with the contents of the %3dest%1 block. Move  %bENV%1 to point to the
 %3dest%1 block.
.APART;
.GROUP;

.NL
%24.%1##Evaluate %9x%1. Within %9x%1, %3lookup%1  will   go to the value
cells for all variable references.
.NL
%25.%1##Restore the old environment. Swap the  contents of the first block of
%bENV%1 with the contents of the appropriate value cells.
.NL
%26.%1##Set %bENV%1 to point at the prior block.
.PT2

.APART;
.GROUP
.FP
To reinforce these notions we supply a more detailed implementation.
We will implement our value cells as elements of the property lists.
The property name will be %3VALUE%1, and the corresponding property
value will be the value cell.
Assume %3x%* and %3y%* are currently bound to %3A%* and
%3B%* respectively; and assume we wish to evaluate:

.BEGIN CENTER;
.PT2
%3λ[[x;y] %9x%3][C;D]%1 
.END
.FP
We assume %bENV%1 is in some well-defined state:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
   part of atom for X         part of atom for Y
 ⊂αααααααπααα⊃ ⊂αααπαα      ⊂αααααααπααα⊃ ⊂αααπαα
 ~ VALUE ~ #αβ→~ A ~ #→...  ~ VALUE ~ #αβ→~ B ~ #→...
 %ααααααα∀ααα$ %ααα∀αα      %ααααααα∀ααα$ %ααα∀αα
    			  
.pt18 			 
 ENV                     
⊂αααα⊃  εααααααααααααλ   
~  #αβα→~*MARK*   #ααβ→⊃		 
%αααα$	εααααααααααααλ ↓	   
	~ last entry ~ ~	   
	εααααααααααααλ ~	   
	     ...
		       ↓
	εααααααααααααλ←$
	~*MARK*   #ααβ→⊃
	εααααααααααααλ ↓
	     ...
.BOXB
.END
.APART
.FP
In this implementation,   the stack is organized in blocks.
The allocation operation  claims space from the top  of the stack and
 puts a special mark in the top of the %bENV%1 stack to delimit
the block of λ-rebindings; that marked entry will also  contain
the %3dest%1 pointer.  The implementation will indicate the 
new block by  pointing to it by %bDEST%1.
The allocation routine is also responsible for filling the name-entries
of the %3dest%1 block. Those entries will be represented as pointers
to the value cell entry on the property list of the atom. 

.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;group;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.KRK;BOXA
   part of atom  for X       part of atom for Y
 ⊂αααααααπααα⊃ ⊂αααπαα      ⊂αααααααπααα⊃ ⊂αααπαα
 ~ VALUE ~ #αβ→~ A ~ #→...  ~ VALUE ~ #αβ→~ B ~ #→...
 %ααααααα∀ααα$ %ααα∀αα      %ααααααα∀ααα$ %ααα∀αα
      	         ↑
 DEST ⊂→αααα→αααα$
⊂αααα⊃↑ ⊂αααααααααααα⊃		      	
~  #αβα→~*MARK*   #ααβ→⊃
%αααα$↑ εαααααααπααααλ ~
      %←β←α#    ~    ~←$
      	εαααααααβααααλ	
 ENV    ~←to Y←#~    ~  
⊂αααα⊃  εααααααα∀ααααλ  
~  #αβα→~*MARK*   #ααβ→⊃		 
%αααα$	εααααααααααααλ ↓	   
	~ last entry ~ ~	   
	εααααααααααααλ ~	   
	     ...
		       ↓
	εααααααααααααλ←$
	~*MARK*   #ααβ→⊃
	εααααααααααααλ ↓
	     ...
.BOXB
.END
.APART
.FP
The %3send%1 operation will fill the %3dest%1 entries for %3x%1 and %3y%1.
The %3next%1 operation will increment the %3dest%1 pointer so that
after all entries have been made to the %3dest%1 block, the %3dest%1 pointer
will indicate the next block of saved bindings.

.GROUP;
With %3x%1 and %3y%1 bound to %3C%1 and %3D%1 in the %3dest%1 block,
we are ready to swap the value cells.
After the swap the picture is:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
   part of atom  for X       part of atom for Y
 ⊂αααααααπααα⊃ ⊂αααπαα      ⊂αααααααπααα⊃ ⊂αααπαα
 ~ VALUE ~ #αβ→~ C ~ #→...  ~ VALUE ~ #αβ→~ D ~ #→...
 %ααααααα∀ααα$ %ααα∀αα      %ααααααα∀ααα$ %ααα∀αα
		↑
 ENV  ⊂αααα→αααα$
⊂αααα⊃↑ ⊂αααααααααααα⊃	
~  #αβα→~*MARK*   #ααβ→⊃
%αααα$↑ εαααααααπααααλ ~
      %←β←α#    ~  A ~ ~
      	εαααααααβααααλ ↓
        ~←to Y←#~  B ~←$
        εααααααα∀ααααλ  
        ~*MARK*   #ααβ→⊃		 
      	εααααααααααααλ ↓	   
	~ last entry ~ ~	   
	εααααααααααααλ ~	   
	     ...
		       ↓
	εααααααααααααλ←$
	~*MARK*   #ααβ→⊃
	εααααααααααααλ ↓
	     ...
.BOXB
.END
.APART
.FP
Now %3x%* and %3y%* have values %3C%* and %3D%* respectively
 and the previous bindings are saved on
the %bENV%1 stack. We may now begin the evaluation of %9x%1
assured that we will get the expected values for %3x%* and %3y%*.
We have also saved sufficient  information to restore the previous values afterwards.
Since we are assuming simple function composition, the
unbind operation can simply "pop" entries off of the top of %bENV%1
into the value cells
rather than swap them with the value cells.

The unbinder  restores the first block
of saved values using the pointers to the value cells as destinations
for  the values.⊗↓An alternative implementation  would only
store the saved values, without explicitly saving the locations, and
without marking the stack. In this implementation  the unbinder would
require an argument describing which variables needed restoring.←   
This stack of previous values is also visited by the  garbage collector;
it may be that the only copy of some value is accessible only through
the %bENV%1 stack. It would be most unfortunate if the garbage collector neglected
to mark that entry and the unbinding mechanism later tried to restore the value.

This implementation works quite well for 
simple λ-binding and lookup. Changing environments is a bit of work, but
the access to the values of variables is relatively rapid, particularly
if we make sure that the value cell is always stored at a known position
relative to the beginning of the property list.
In describing this implementation we have used more representation than
might seem appropriate. In particular the representation of the value cell
as a linked list seems unnecessarily explicit. This was done to illuminate
the pointer modifications involved in binding and unbinding.

We would like to implement functional arguments in this shallow binder.
  Recall how deep binding     coped.
When we recognized  an instance of a functional argument we saved a pointer to 
the current environment. When we %6applied%*
the functional argument we restored the symbol table in such a way
that global variables were accessed in the saved environment while
local variables were found in the current environment.
We must try to do the same with the shallow-binding. 
The action taken  when a functional argument is recognized is quite similar
to our previous solution:
when %3function%* is seen, save the current %bENV%1 pointer.
This setting of %bENV%1 establishes the binding environment, and is therefore
callled the %2binding context pointer%1.
 The action  therefore, manufactures a triple
%3(FUNARG#%*<function>#<binding#context#pointer>%*)%1. 

However, the action required when we 
wish to apply the functional argument is much more complicated. In the 
deep binding implementation
we just set up a new access chain such that the local table referred to
 binding environment   saved by the %3FUNARG%* construction.
The problem with the shallow-binder is that %bENV%1
 only reflects the %6incremental%* changes in the environments
during the computation. To retrieve the environment current when  the
functional argument was bound, we must unwind %bENV%1 back to the binding
environment; we must also save the current activation environment
so that we may return to %6it%* when finished with the functional argument.
Since we are dealing with a functional argument, rather than a functional value,
we can easily locate the binding context pointer. The pointer is %6below%1 the
current %bENV%1 in the stack. We search down the stack for that  saved pointer,
swapping back the saved value cells. When we reach the binding context pointer
we stop. At that time the value cells have been restored to the
binding environment and the segment of the stack between the
activation environment and the binding environment accurately reflects
the bindings which were made between binding and activation; that is,
that segment of the stack is deep bound.
That stack segment must be saved so that the activation environment can be
restored, thus %bENV%1 is not restored to the binding context, but remains
where it was.

This process is complex enough to warrant an example.
.CENT(An example of shallow binding and %3FUNARG%*)

.BEGIN INDENT 0,5;GROUP
%2I%* Assume that %3x%* initially has value %31%* and the %bSP%1 pointer
is at location %bSP1%*,
.PT2
%2II%* then assume that a λ-binding rebinds %3x%* to %32%*;
.PT2
%2III%* in this new context, assume a functional argument, %3g%*,
is to be bound to a function-variable %3f%*.
.PT2
%2IV-V%* As the computation continues %3x%* is rebound first to %33%* and
within %6that%* context rebound again to %34%*.
.PT2
%2VI%* Finally %3f%* is applied; this will resurrect %3g%*⊗↓From the   value#cell
of %3f%* as %3(FUNARG G SP2)%*.← requiring
a restoration of the environment current at step %2III%*.
.PT2
.END
.GROUP
.FP
Steps %2I%* through %2V%* would lead to the following sequence.
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA
.KRK
					   F: (FUNARG G #)
X: 1			X: 2		   X: 2	        ↓
      εααα∀αααλ	             εαααβαααλ          ⊂ααα←ααα$ 
SP1 α→~*MARK* ~ =II=>  SP2 α→~ X ~ 1 ~ =III=>   ↓       
      εαααπαααλ	             εααα∀αααλ      SP2 ∀α→~ X ~ 1 ~ 
	. . .		     ~*MARK* ~		     . . .
			     εαααπαααλ
			       . . .
		       SP1 α→~ . . . ~


      X: 3		     X: 4

=IV=> SP3 αα→~ X ~ 2 ~  =V=> SP4 εαααβαααλ
	     εαααβαααλ	      %α→~ X ~ 3 ~
	       . . .             εαααβαααλ

      SP2 αα→~ X ~ 1 ~		   . . .
	     εαααβαααλ
	       . . .
.BOXB
.END
.APART
.FP
Now to apply the functional argument: %3(FUNARG G SP2)%*.
This is accomplished by  tracing down the %bSP%1 stack with a pointer %bSP*%*,
moving from %bSP4%* --the#current#stack#pointer-- down to %bSP2%*
--the#%3FUNARG%*#pointer--, reversing all the intervening bindings on SP
and putting the saved values back into the   value#cell.
The pattern of these reversals must be saved; we do this by swapping the
values back into the stack segment between %bSP4%1 and %bSP2%1.
.GROUP
Thus,  steps %2VII%* and %2VIII%*:
.BEGIN SELECT b;NOFILL;PREFACE 0 MILLS;
.TURN OFF "%","#","α","←";
.TURN ON "∞" FOR "%";
.BOXA;KRK
      X:3 		              X: 2
               . . .		              . . . 
       SP4 α→~ X ~ 4 ~	     	      SP4 α→~ X ~ 4 ~
	     εαααβαααλ		  	    εαααβαααλ
               . . .		              . . .
=VII=> SP3 α→~ X ~ 2 ~←α SP*  =VIII=> SP3 α→~ X ~ 3 ~ 
	       . . .		      	      . . .
	     εαααβαααλ			    εαααβαααλ
       SP2 α→~ X ~ 1 ~		      SP2 α→~ X ~ 1 ~←α SP*
	       . . .			      . . .

.BOXB
.END
.APART
.FP
Now we are in a position to evaluate the call on %3g%*; when we are finished
with %3g%* we will use the unbinding mechanism to reinstate the world
as it existed at %bSP4%*. This process will restore the value#cells using
the areas of the stack between %bSP2%* and %bSP4%*.

Functional arguments are more difficult since there
is only one symbol table, not the stack of tables implicit in the 
deep binding implementation. 
True, the information necessary to recover an environment
is present in %bSP%1, but now it is more expensive to retrieve it.

Though the  stack implementation of shallow binding 
%6will%* perform for functional arguments,
it will involve even more complexity if we wish to handle functional values.
The difficulty  is the same as that for  the stack implementation of
deep binding: the %3FUNARG%* will point
"up" the %bSP%1 stack rather than "down".
A straightforward application of the technique used for functional arguments 
 will not work. At the time we wished to apply the functional value
its saved %bSP%1-pointer will be pointing into a section of the %bSP%1 stack
which no longer reflects the proper state. 
For when we leave the environment which created the
functional value the current unbinding mechanism will cut the stack back to 
the point which existed when we entered that environment.

The generalization of this shallow binding scheme to functional values
is possible. There are two problems to be solved. First, the 
storage for %bENV%1 and %bDEST%1 must be generalized to be tree-like rather
than stack-like. This generalization is not  simply a problem of shallow binding.
The deep binding scheme builds a tree isomorphic to the shallow tree;
only  the information saved in the respective trees differs.
The problem which  the shallow binder must solve is how to 
rebind from the activation environment to the binding environment.
The functional argument case was simplified since the binding environment was
on the same branch of the environment tree. In the more general case
the binding environment will be on a different branch.
We will investigate some solutions to this problem in the next section.
.END "SHAL"
.ss(Strategies for Full LISP Implementation,,P228:)
.FP
The discussion of the last three sections should be related to the earlier
discussion of binding strategies, Weizenbaum environments, functional arguments
and the non-recursive evaluators.
Our mapping of the binding implementations (shallow or deep) onto a stack 
is sufficient for  the great majority of  LISP programs. However as 
the LISP community explores new ways of using the language, they 
expect that the full power of functional values be available; and have
proposed extensions in the LISP control structure to allow  non-recursive
control. Since these topics are of current research interest it is not
clear how lasting their impact will be. We will sketch a few of the
ideas involved and indicate how the techniques we have discussed in this chapter
can be applied.

In the implementation of %3eval%1 of {yonss(P6)}
  we represented
symbol tables as list-structure. Later, when we introduced the %3function%1
construct, this generality became  necessary.
As long as a %3FUNARG%* construct
accessed a table, then that table was retained; 
 symbol tables were then
 a garbage collectible commodity. 
Essentially we had removed
the stack-like behavior of symbol-table accesses which occurs most of the
time and replaced it with a  general scheme which 
works for all cases but incurs a significant overhead in even the most
simple of function calls. 

We would like an intermediate solution:
one which works for all cases and minimizes overhead in the
typical call. Such a scheme can indeed be implemented.
Recall our discussion of garbage collection in {yonss(P146)}. There we said
that a garbage collector was used in LISP since the interrelationships
which we generated in the data structure manipulations were
sufficiently intertwined that it was not possible to use less
sophisticated methods to determine whether a structure was still active.

Symbol tables %6are%* data structures; the discussion of
Weizenbaum environments in {yonss(P77)} should have convinced you of that.
They are chained
together in a manner reminiscent of that of our implementation
of S-exprs; indeed as we have just mentioned LISP's attitude toward
management of such tables was to garbage collect them. However the %6behavior%* of 
tables during the execution of a program is much less complex than that
of arbitrary list structure. As we have just seen, the behavior
is predictable except for procedure-valued variables.
A solution giving a reasonable implementation based on
the alternative storage management scheme of ⊗→reference counter↔←s, which we
described on {yon(P145)}, is described in ⊗↑[Bob#73a]↑.
Several other generalized control schemes  have been proposed;
for example ⊗↑[Con#73]↑, ⊗↑[Gre#74]↑, ⊗↑[Mon#75]↑, and ⊗↑[Wegb#75]↑.
The intent of all these schemes is 
that minimal overhead be experienced
if a  program does not use the more
exotic features:  a stack-like device results. A larger toll is
paid for use of more general control regimes.




It %6is%* possible to  combine  the use of the value cell
with either
shallow or deep  strategies.
We have %6both%1 a value cell and either
name-value trees or  shallow bound p-lists. We will try to use
the value#cell as much as possible.
We associate an extra piece of information with each value attached to
any value#cell, telling the binding time of that variable.
We have a global indicator telling the current context which we are using:
E%4current%*, say. When we want the value of a variable, we first go to the
augmented value#cell; if the binding time indication is that of
E%4current%1, then the  value is correct and we take it.  If the
indicators disagree, we use the full %3lookup%1 strategy;
when we find the variable we update the value#cell and change the binding
time indicator to E%4current%*. This way we only search the stacks for the
first access to a variable; after that we can justifiably use the value cell until 
we change context again. This scheme,
called  %2⊗→cache#value#cells↔←%1, has been implemented in ⊗↑[Mud#75]↑.


Finally, we describe a   full shallow binding implementation of functional
values (⊗↑[Gre#74]↑). We identified the critical problem as that of  discovering the
path between the activation environment and the binding
environment.  Let us call
the two nodes E%4act%1 and E%4bind%1. With any node in the tree is associated
a flag named %3active%1; only nodes on the currently active branch are marked
%3active%1. It will be the responsibility of the binding and unbinding routines
to maintain  this flag. In the current situation, E%4act%1 is on the active
branch and E%4bind%1 is not. We go to the node E%4bind%1 and search
back down its  branch, looking for a node marked %3active%1. Call this node
E%4inter%1. E%4inter%1 represents the intersection of the active 
branch with the branch tipped in E%4bind%1.

.BEGIN SELECT g;NOFILL;PREFACE 0 MILLS;GROUP;
.TURN OFF "%","#","\";
.TURN ON "∞" FOR "%";
.BOXA;KRK
		∞1E∞4act∞g     ∞1E∞4bind∞g
		 ∞FH∞*      ∞FG∞*
		  ∞FH∞*    ∞FG∞*
		   ∞FH∞*  ∞FG∞*
		    ∞FHG∞*
		    ∞1E∞4inter∞g
		     ↓
		   . . .
.BOXB
.END
.FP
We now go  E%4act%1 and unbind down to E%4inter%1, swapping the
value cells as we go. At E%4inter%1 we  bind up to E%4bind%1, still
swapping value cells. When we reach E%4bind%1 the binding environment has been
restored, and the  path from E%4bind%1 through E%4inter%1 to E%4act%1
contains the necessary information to allow us to rebind to E%4act%1 if
desired.

The winding and unwinding of value cells is  a time consuming process,
much more  so than the context swap used in a deep binding scheme.
One objection to this implementation of  the 
shallow scheme is that it optimized for the
case that many of the references in the new environment will
be to free variables: those variables which are non-local, but are not
globally bound. If a variable is local or global, its access is trivial.
If  there are no free references in the new environment, then this shallow swap 
is not needed. Alternative schemes exist which allow  the fast access 
of shallow binding and allow the fast context swap of deep binding.
.SS(Epilogue,,P260:)
.FP
Most  programming languages are much less complex than LISP;
they are far less flexible in their control regimes or
 their symbol accessing mechanisms.
   In Fortran there is a simple relationship between
variables and memory locations which will contain their values;
a Fortran evaluator can assign fixed locations to the variables
in a program.
In Algol, there is a simple relationship between variables and positions
in the run-time stack; an Algol evaluator cannot assign fixed locations, but
it can replace the variable lookup with a simple address calculation. This
is partly due to Algol's use of static binding⊗↓This is another
benefit of referential transparency ({yon(P261)}).← and partly due to its
restrictions on procedure-valued variables.
These kinds of restrictions allow Fortran and Algol compilers  to
produce efficient code.

In  the most general uses of LISP, 
both the quality and the quantity of variables can change.
Arbitrary properties can be associated with atoms at run-time.
Indeed, the symbol table mechanism of LISP is more reminiscent of
that associated with the compilers for other languages.  For these 
languages it is the compiler which performs the mapping
from source language to running machine code.  It is the compiler's 
responsibility to discover the properties associated with each variable.
The compiler can do this because the semantics of the language is such
that at compile time all, or almost all, of the  properties 
of the variables are known.
This is not true for LISP.  In general you cannot tell until run time what
the attributes of a particular atom are.  The situation is really even worse
than this.  Since programs and data are indistinguishable, we can construct  a 
list using the data structure facilities and the turn right around and evaluate
that list as a representation of a LISP expression.

However,
a large majority of LISP computations fall into a much more
disciplined set, and for those computations, 
some of the ideas available for Fortran or Algol
translators are applicable. If we don't use all of the generality available in 
the language, we can reduce some of the run-time overhead.
For these kinds of computations, it might be appropriate to compile out
the unneeded generality.
There are LISP compilers, typically written
in LISP. They can make many decisions at compile time
about the properties of variables;  and given comparable information about
a program's characteristics can produce code comparable to that produced
by Algol and Fortran#(⊗↑[Fat#73]↑).

In  the most general cases, the compiled code
may be interspersed with calls on %3eval%*.
This implies that compiled and interpreted code must be able to 
communicate with each other.  A piece of compiled code can call a 
λ-expression or conversely.  The execution
of the program should be totally transparent as to whether any, or all, or
none of the functions are compiled.  This means that the calling
sequences for both kinds of functions must be compatible. Less
obvious and by far more troublesome, is the communication of the values of free
variables. The next chapter  discusses
the run-time behavior required for implementations of LISP-like languages
including a discussion of LISP compilers.


.END "JRA";